能量采集[NOI2010][Codevs1937]

来源:互联网 发布:isis网络恐怖主义活动 编辑:程序博客网 时间:2024/05/18 01:30

题目描述 Description

栋栋有一块长方形的地,他在地上种了一种能量植物,这种植物可以采集太阳光的能量。在这些植物采集能量后,栋栋再使用一个能量汇集机器把这些植物采集到的能量汇集到一起。

栋栋的植物种得非常整齐,一共有 n 列,每列有 m 棵,植物的横竖间距都一样,因此对于每一棵植物,栋栋可以用一个坐标 (x,y) 来表示,其中 x 的范围是 1n ,表示是在第 x 列, y 的范围是 1m ,表示是在第 x 列的第 y 棵。

由于能量汇集机器较大,不便移动,栋栋将它放在了一个角上,坐标正好是 (0,0)

能量汇集机器在汇集的过程中有一定的能量损失。如果一棵植物与能量汇集机器连接而成的线段上有 k 棵植物,则能量的损失为 2k+1 。例如,当能量汇集机器收集坐标为 (2,4) 的植物时,由于连接线段上存在一棵植物 (1,2) ,会产生 3 的能量损失。注意,如果一棵植物与能量汇集机器连接的线段上没有植物,则能量损失为 1 。现在要计算总的能量损失。

下面给出了一个能量采集的例子,其中 n=5m=4 ,一共有 20 棵植物,总共产生了 36 的能量损失。


输入描述 Input Description

一行,为两个整数 nm


输出描述 Output Description

仅一个整数,表示总共产生的能量损失。


样例输入 Sample Input

【样例输入1】
5 4

【样例输入2】
3 4


样例输出 Sample Output

【样例输出1】
36

【样例输出2】
20


数据范围及提示 Data Size & Hint

对于 10% 的数据: 1n,m10

对于 50% 的数据: 1n,m100

对于 80% 的数据: 1n,m1000

对于 90% 的数据: 1n,m10,000

对于 100% 的数据: 1n,m100,000


分析

对于坐标为 (x,y) 的整数,与能量汇集机器连接而成的线段上有 gcd(x,y)1 棵植物

数据不大,暴力求出每一对 (x,y)gcd,80 分妥妥的

因为 min(n,m)<=100000 ,所以对于任意的 (x,y) 都有 gcd(x,y)<=100000 ,所以可以枚举 gcd ,因为公因数为 d 的所有 (x,y)[nd][md] 对,令 fd=[nd][md] 所以最大公因数为 d 的有 fd[min(n,m)d]i=2fid ( d 从大到小枚举 )


代码

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;LL ans;LL f[100001];int n,m;int main(){    scanf("%d%d",&n,&m);    if(n > m)        swap(n,m);    for(int i=1;i<=n;++i)        f[i] = LL(n/i)*LL(m/i);    for(int i=n;i>=1;--i){        for(int j=(i<<1);j<=n;j+=i)            f[i] -= f[j];        ans += ((i-1)*2+1)*f[i];    }    printf("%lld",ans);    return 0;}
0 0
原创粉丝点击