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 } 

 

2021.1.24 二刷做出来了!!!蒟蒻落泪,虽然是道入门题但做出来了数论题感觉人生圆满了

posted @ 2021-01-17 15:58  acmloser  阅读(65)  评论(0编辑  收藏  举报