BZOJ 2226 [Spoj 5971] LCMSum | 数论拆式子
题目:
http://www.lydsy.com/JudgeOnline/problem.php?id=2226
题解:
题目要求的是Σn*i/gcd(i,n) i∈[1,n]
把n提出来变成Σi/gcd(i,n) i∈[1,n] 最后乘个n
设gcd(i,n)==d 我们枚举约数可以得到
∑(∑i/d*(gcd(i,n)==d)) (外面的Σ枚举d)
把i/d这个式子除以d可以得到
Σ( Σj*(gcd(j,n/d)==1) ) (外面Σ枚举d,j与n互质)
由于n/d与d等价
Σ( Σj*(gcd(j,d)==1) ) (外面Σ枚举d,j与n互质)
所以求小于等于i的所有与其互质的自然数之和
利用欧拉函数的性质有结论 : i*φ(i)/2
所以枚举i求解
#include<cstdio> #define N 2000005 #define MaxN 1000000 typedef long long ll; using namespace std; ll phi[N],ans; bool nonprime[N]; int prime[N],tot,T,n; int main() { phi[1]=1; for (int i=2;i<=MaxN;i++) { if (!nonprime[i]) phi[i]=i-1,prime[++tot]=i; for (int j=1;j<=tot;j++) { if ((ll)prime[j]*i>MaxN) break; nonprime[i*prime[j]]=1; if (i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j]; break; } phi[i*prime[j]]=phi[i]*(prime[j]-1); } } for (int i=2;i<=MaxN;i++) phi[i]=phi[i]*i/2; scanf("%d",&T); while (T--) { scanf("%d",&n);ans=0; for (int i=1;i*i<=n;i++) if (n%i==0) { ans+=phi[i]; if (i*i<n) ans+=phi[n/i]; } printf("%lld\n",ans*n); } return 0; }