首页 > 代码库 > 洛谷P2398 GCD SUM

洛谷P2398 GCD SUM

题目描述

for i=1 to n

for j=1 to n

 sum+=gcd(i,j)

给出n求sum. gcd(x,y)表示x,y的最大公约数.

输入输出格式

输入格式:

 

n

 

输出格式:

 

sum

 

输入输出样例

输入样例#1:
2
输出样例#1:
5

说明

数据范围 30% n<=3000 60% 7000<=n<=7100 100% n<=100000

——————————————————————————————————

又是数论QAQ

我们可以枚举k

ans=∑k*f[k]

f[k]表示gcd(i,j)=k的个数

f[k]=(n/k)(n/k);

但是我们还要扣掉前面gcd=2k,3k,4k........的

所以f[k]=[n/k]^2-(f[2k]+f[3k]+....)

复杂度是n*(1+1/2+1/3+...+1/n)

根据定积分公式$\int_0^n 1/x{\rm d}x $=ln(n)-ln(1)=ln(n)

所以总复杂的为nln(n)

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int M=100007;
LL read(){
    LL ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
LL n,f[M],ans;
int main()
{
    n=read();
    for(int i=n;i>=1;i--){
        f[i]=(n/i)*(n/i);
        for(int j=i*2;j<=n;j+=i) f[i]-=f[j];
        ans+=i*f[i];
    }printf("%lld\n",ans);
    return 0;
}
View Code

 

洛谷P2398 GCD SUM