Longge's problem
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 6918 | Accepted: 2234 |
Description
Longge is good at mathematics and he likes to think about hard mathematical problems which will be solved by some graceful algorithms. Now a problem comes: Given an integer N(1 < N < 2^31),you are to calculate ∑gcd(i, N) 1<=i <=N.
"Oh, I know, I know!" Longge shouts! But do you know? Please solve it.
"Oh, I know, I know!" Longge shouts! But do you know? Please solve it.
Input
Input contain several test case.
A number N per line.
A number N per line.
Output
For each N, output ,∑gcd(i, N) 1<=i <=N, a line
Sample Input
2 6
Sample Output
3 15
Source
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <math.h> 5 #include <string.h> 6 #define MAXN 100010 7 #define INF 0x7fffffff 8 using namespace std; 9 long long a[110000]= {0},b[110000],nu,c[10000][2],cn; 10 void init() 11 { 12 nu=0; 13 long long i,j; 14 for(i=2; i<110000; i++) 15 { 16 if(!a[i]) 17 { 18 b[nu++]=i; 19 j=i*i; 20 while(j<110000) 21 { 22 a[j]=1; 23 j+=i; 24 } 25 } 26 } 27 } 28 void fun(long long x) 29 { 30 long long i; 31 memset(c,0,sizeof(c)); 32 cn=0; 33 for(i=0; b[nu]<=x&&i<nu; i++) 34 { 35 if(x%b[i]==0) 36 { 37 c[cn][0]=b[i]; 38 while(x%b[i]==0) 39 { 40 c[cn][1]++; 41 x/=b[i]; 42 } 43 cn++; 44 } 45 } 46 if(x!=1) 47 { 48 c[cn][0]=x; 49 c[cn++][1]=1; 50 } 51 } 52 long long so(long long n,long long x) 53 { 54 long long i=0,sum=n; 55 while(x) 56 { 57 if(x&1) 58 { 59 sum=sum/c[i][0]*(c[i][0]-1); 60 sum*=c[i][1]; 61 } 62 i++; 63 x>>=1; 64 } 65 return sum; 66 } 67 long long work(long long n) 68 { 69 long long i,size=1<<cn,sum=0; 70 for(i=0;i<size;i++) 71 { 72 sum+=so(n,i); 73 } 74 return sum; 75 } 76 int main() 77 { 78 init(); 79 long long n; 80 while(~scanf("%I64d",&n)) 81 { 82 fun(n); 83 printf("%I64d\n",work(n)); 84 } 85 }
设函数g(n) = gcd(i,n) (1<=i<=n),由积性函数的定义,g(n)=g(m1)*g(m2) (n=m1*m2 且 (m1, m2)= 1),所以g是积性函数。由具体数学上的结论,积性函数的和也是积性的。所以f(n) = ∑gcd(i, n)也是积性函数。由初等数论中的定理,如果f(n)是不恒为0的数论函数,n>1时 n=p1^a1*p2^a2*...*ps^as,那么f(n)是积性函数的充要条件是f(1)=1,及f(n) = f(p1^a1)*f(p2^a2)*...f(pr^ar)。所以只要求f(pi^ai)就好,如果d是n的一个约数,那么1<=i<=n中gcd(i,n) = d的个数是phi(n/d),即n/d的欧拉函数
f(pi^ai) = Φ(pi^ai)+pi*Φ(pi^(ai-1))+pi^2*Φ(pi^(ai-2))+...+pi^(ai-1)* Φ(pi)+ pi^ai *Φ(1)
= pi^(ai-1)*(pi-1) + pi*pi^(ai-2)*(pi-1)....+pi^ai
= pi^ai*(1+ai*(1-1/pi))
f(n) = p1^a1*p2^a2...*pr^ar*(1+a1*(1-1/p1))*(1+a2*(1-1/p2))*...
= n*(1+a1*(1-1/p1))*(1+a2*(1-1/p2))*...
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <math.h> 5 #include <string.h> 6 #define MAXN 100010 7 #define INF 0x7fffffff 8 using namespace std; 9 int a[50000]= {0},b[50000],nu,c[70][2],cn; 10 void init() 11 { 12 nu=0; 13 long long i,j; 14 for(i=2; i<50000; i++) 15 { 16 if(!a[i]) 17 { 18 b[nu++]=i; 19 j=i*i; 20 while(j<50000) 21 { 22 a[j]=1; 23 j+=i; 24 } 25 } 26 } 27 } 28 void fun(long long x) 29 { 30 long long i; 31 memset(c,0,sizeof(c)); 32 cn=0; 33 for(i=0; b[nu]<=x&&i<nu; i++) 34 { 35 if(x%b[i]==0) 36 { 37 c[cn][0]=b[i]; 38 while(x%b[i]==0) 39 { 40 c[cn][1]++; 41 x/=b[i]; 42 } 43 cn++; 44 } 45 } 46 if(x!=1) 47 { 48 c[cn][0]=x; 49 c[cn++][1]=1; 50 } 51 } 52 long long work(long long n) 53 { 54 long long i,sum=n; 55 for(i=0;i<cn;i++) 56 { 57 sum=sum+sum*c[i][1]*(c[i][0]-1)/c[i][0]; 58 } 59 return sum; 60 } 61 int main() 62 { 63 init(); 64 long long n; 65 while(~scanf("%I64d",&n)) 66 { 67 fun(n); 68 printf("%I64d\n",work(n)); 69 } 70 }