题目:求sum(gcd(i,j)),(1<=i<j<=n)
题解:我们设答案为ans[n],ans[n]=ans[n-1]+gcd(1,n)+gcd(2,n)+...+gcd(n-1,n);接下来的问题是如何求gcd(1,n)+gcd(2,n)+...+gcd(n-1,n);
设g[n]=gcd(1,n)+gcd(2,n)+...+gcd(n-1,n); 设p(i)表示目前为止与n的gcd为i的数有几个?则g[n]=sum(p[i])(1<=i<=n);
假设gcd(x,n)=i,那么显然gcd(x/i,n/i)=1,所以p[i]即为phi(n/i)的值。
所以我们只需预处理出phi的值就可以了。
程序:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #define maxn 4000009 using namespace std; typedef long long ll; ll phi[maxn],g[maxn],f[maxn]; int n; int main() { scanf("%d",&n); for (int i=1;i<maxn;i++) phi[i]=0; phi[1]=1; for (int i=2;i<maxn;i++) { if (phi[i]) continue; for (int j=i;j<maxn;j+=i) { if (!phi[j]) phi[j]=j; phi[j]-=phi[j]/i; } } for (int i=1;i<maxn;i++) for (int j=i+i;j<maxn;j+=i) g[j]+=phi[j/i]*i; f[2]=g[2]; for (int i=3;i<maxn;i++) f[i]=f[i-1]+g[i]; while (n) { printf("%lld ",f[n]); scanf("%d",&n); } return 0; }