思路: ans[n]= ans[n-1] + { (n,1),(n,2).....(n,n)} 现在任务 是 计算 { (n,1),(n,2).....(n,n)}(k=n的任意因子)
很明显 所有能取的k均为n的因子可以 sqrt(n) 内枚举。 若 p 为n的因子 那么 d(n,p) =p*p * {(n/p,1) ,(n/p,2) 。。。(n/p,n/p)}(后面这部分 k 取 1) 那么任务就转化成求 f(n) f(n)表示 {(n,1),(n,2) ....(n,n)}当k等于1时候的值。 k等于1 相当于 枚举每个因子 p 。。求 sum*n 这边的sum表示与n/p互质的所有数之和。 sum=phi(n/p)*n/p ;
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<time.h> #include<string> #define REP(i,n) for(int i=0;i<n;++i) #define REP1(i,a,b) for(int i=a;i<=b;++i) #define REP2(i,a,b) for(int i=a;i>=b;--i) #define MP make_pair #define LL long long #define X first #define Y second #define MAXN 500005 using namespace std; LL MOD; LL f[MAXN]; LL sum[MAXN]; LL phi[MAXN]; LL ans[MAXN]; void getphi() { for(int i=1; i<MAXN; i++) phi[i]=i; for(int i=2; i<MAXN; i+=2) phi[i]>>=1; for(int i=3; i<MAXN; i+=2) if(phi[i]==i) { for(int j=i; j<MAXN; j+=i) phi[j]=phi[j]/i*(i-1); } } void init() { MOD=1; REP(i,32)MOD*=2; getphi(); for(int i=1;i<MAXN;++i) sum[i]=(phi[i]*i/2)%MOD; for(int i=1;i<MAXN;++i) { int j; f[i]=i; for(j=1;j*j<i;++j) { if(i%j==0) { f[i]=(f[i]+sum[j]*i)%MOD; f[i]=(f[i]+sum[i/j]*i)%MOD; } } if(j*j==i) { f[i]=(f[i]+sum[j]*i)%MOD; } } ans[1]=1; for(int i=2;i<MAXN;++i) { ans[i]=(ans[i-1]+f[i]); if(ans[i]>MOD)ans[i]-=MOD; int j; for(j=2;j*j<i;++j) if(i%j==0) { ans[i]=(ans[i]+((f[i/j]*j)%MOD)*j)%MOD; ans[i]=(ans[i]+((f[j]*(i/j))%MOD)*(i/j))%MOD; } if(j*j==i) { ans[i]=(ans[i]+((f[j]*j)%MOD)*j)%MOD; } ans[i]=(ans[i]+(LL)i*i)%MOD; } } int main() { init(); int tt,ri=0; scanf("%d",&tt); while(tt--) { int n; scanf("%d",&n); printf("Case #%d: %I64d\n",++ri,ans[n]); } return 0; }