poj 2480 数学
题意:给定一个整数n (1<n<2^31), 求1~n的数与n的最大公约数之和,即 ∑gcd(i, n) (1<=i <=n) 。
分析:枚举n的因数k,求有多少个 i ,使gcd(i,n)=k。
设gcd(i,n)=k, 其中 i=ak, n=bk, 则gcd(ak, bk)=k => gcd(a,b)=1, 所以有φ(b)个 i ,使gcd(i,n)=k。
答案为: ∑k*φ(n/k) (k|n)
#define Max 46355 LL pri[Max], p, n; LL ans; bool vis[Max] ; void getPrime(LL n){//大范围内素数的线性筛法 for(LL i = 2; i <= n; i++){ if( !vis[i]) pri[p++] = i; for(int j = 0;j < p && pri[j] * i <= n; j++){ vis[pri[j] * i] = true; if(i % pri[j] == 0) break; } } } const int M = 20; LL cnt[M], pr[M], q; void init(LL n){ memset(cnt, 0, sizeof cnt);//缺少这句,RE半天 q=0; ans=0; for(LL i = 0; pri[i] * pri[i] <= n ; i++){ if(n%pri[i]==0){ pr[q] = pri[i]; while(n % pri[i] == 0) { n /= pri[i]; cnt[q]++; } q++; } } if(n > 1) {pr[q] = n; cnt[q]++; q++;} } LL euler1(LL n){//求φ(n) LL res = n; for(LL i = 0; pri[i] * pri[i] <= n ; i++) if(n % pri[i] == 0){ res = res / pri[i] * ( pri[i] - 1 ); while(n % pri[i] == 0) n /= pri[i]; } if(n > 1) res = res / n * (n - 1); return res; } void d(LL s, int i, int f){ if(s*s>n) return; if(f){ ans += s*euler1(n/s); if(s*s!=n) ans += (n/s)*euler1(s); } //cout<<s<<' '<<i<<' '<<pr[i]<<' '<<cnt[i]<<' '<<endl; if(i>=q) return; d(s, i+1, 0); FOR(j, 0, cnt[i]){ s*=pr[i]; d(s, i+1, 1); } } /* void d(LL s, int i, int f){ if(f){ ans += s*euler1(n/s); //if(s*s!=n) ans += (n/s)*euler1(s); } //cout<<s<<' '<<i<<' '<<pr[i]<<' '<<cnt[i]<<' '<<endl; if( i>=q ) return; d(s, i+1, 0); FOR(j, 0, cnt[i]){ s*=pr[i]; d(s, i+1, 1); } }*/ int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif getPrime(Max); while(cin>>n){ init(n); d(1, 0, 1); /*ans = 0; int sq=sqrt(n*1.0); FOE(i,1,sq){ if(n%i==0){ ans+=i*euler1(n/i); if(i*i!=n) ans+=(n/i)*euler1(i); } }*/ cout<<ans<<endl; } return 0; }