Longge's problem POJ - 2480
作者:互联网
数论的时间复杂度我真的越来越懵逼.....找个时间再琢磨一下
这道题枚举一定超时.将n分解质因数后也没找到什么规律.因此只能从gcd返回值入手.在int范围内约数最多是1536个.因此是可以枚举约数的
看了大佬的思路:
假设当前数字为i,设gcd(i,n)==k.那么为了简化计算.我们可以找与n的约数是k的i有多少个.已知gcd(i/k,n/k)=1.也就是说找与n/k互质的数有多少个.可以想到欧拉函数.即phi[n/k]个.我们枚举n的每一个约数.对其求和即为答案
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 typedef long long ll; 5 const int N = 1e5+10; 6 int prime[N],cnt; 7 bool st[N]; 8 void GetPrime(int n) 9 { 10 for(int i=2;i<=n;i++) 11 { 12 if(!st[i]) prime[cnt++] = i; 13 for(int j=0;prime[j]<=n/i;j++) 14 { 15 st[i*prime[j]] = 1; 16 if(i%prime[j]==0) break; 17 } 18 } 19 } 20 ll phi(ll n) 21 { 22 ll res = n; 23 for(int i=0;prime[i]<=n/prime[i];i++) 24 { 25 if(n%prime[i]==0) 26 { 27 res = res/prime[i]*(prime[i]-1); 28 while(n%prime[i]==0) n/=prime[i]; 29 } 30 } 31 if(n>1) res = res/n*(n-1); 32 return res; 33 } 34 int main() 35 { 36 ll n; 37 GetPrime(1e5); 38 while(scanf("%lld",&n)!=EOF) 39 { 40 ll ans = 0; 41 for(int i=1;i<=n/i;i++) 42 { 43 if(n%i==0) ans+=i*phi(n/i); 44 if(n%i==0&&n/i!=i) ans+=n/i*phi(i); 45 } 46 printf("%lld\n",ans); 47 } 48 return 0; 49 }
标签:约数,gcd,Longge,res,ll,int,枚举,POJ,problem 来源: https://www.cnblogs.com/newblg/p/14289216.html