【[SDOi2012]Longge的問題】
阿新 • • 發佈:2019-01-02
求\(\sum_{i=1}^ngcd(i,n)\)
考慮列舉\(gcd\),現在答案變成這樣
\(\sum_{d|n}d*f(d)\)
\(f(d)=\sum_{i=1}^n [gcd(i,n)==d]\)
考慮一下\(f(d)\)如何求
顯然\(f(d)=\varphi(n/d)\)
因為所有與\(n/d\)互質的數乘上\(d\)就是和\(n\)互質的數了
所有答案就是\(\sum_{d|n}d*\varphi(n/d)\)
程式碼
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #define re register #define LL long long #define maxn 65580 inline int read() { char c=getchar(); int x=0; while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar(); return x; } int phi[maxn],p[maxn],f[maxn]; LL n,ans; int U; inline LL solve(LL x) { if(x<=U) return phi[x]; LL now=1; for(re int i=1;i<=p[0];i++) if(x%p[i]==0) { LL tot=1; while(x%p[i]==0) tot*=p[i],x/=p[i]; now*=(p[i]-1)*(tot/p[i]); if(x==1) break; } if(x!=1) now*=(x-1); return now; } int main() { scanf("%lld",&n); f[1]=1,phi[1]=1; U=std::sqrt(n); for(re int i=2;i<=U;i++) { if(!f[i]) p[++p[0]]=i,phi[i]=i-1; for(re int j=1;j<=p[0]&&p[j]*i<=U;j++) { f[p[j]*i]=1; if(i%p[j]==0) { phi[p[j]*i]=phi[i]*p[j]; break; } phi[p[j]*i]=phi[i]*(p[j]-1); } } for(re LL i=1;i*i<=n;i++) if(n%i==0) { ans+=i*solve(n/i); if(n/i!=i) ans+=(n/i)*solve(i); } std::cout<<ans; return 0; }