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. 

Input

Input contain several test case. 
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

 

 

 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 }
View Code

 

 

设函数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))*...

 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 }
View Code

 

 

posted on 2014-04-27 09:42  ERKE  阅读(273)  评论(0编辑  收藏  举报