欧拉函数

欧拉函数
欧拉函数是数论中很重要的一个函数,欧拉函数是指:对于一个正整数n,小于n且和n互质的正整数的个数,记做:φ(n),其中φ(1)被定义为1,但是并没有任何实质的意义。

定义小于n且和n互质的数构成的集合为Zn,称呼这个集合为n的完全余数集合。

显然,对于素数p,φ(p)= p -1.对于两个素数p、q,他们的乘积n = pq 满足φ(n) =(p-1)(q-1)

         证明:对于质数p,q,满足φ(n) =(p-1)(q-1)
         考虑n的完全余数集Zn = { 1,2,....,pq -1}
         而不和n互质的集合由下面三个集合的并构成:
         1) 能够被p整除的集合{p,2p,3p,....,(q-1)p} 共计q-1个
         2) 能够被q整除的集合{q,2q,3q,....,(p-1)q} 共计p-1个
         3) {0}
         很显然,1、2集合中没有共同的元素,因此Zn中元素个数 = pq - (p-1 + q- 1 + 1) = (p-1)(q-1)

         上式中黑体的1是它本身,因为是小于它且和它互质的数,所以当然必须减去自身了。

欧拉函数的定义:E(k)=([1,n-1]中与n互质的整数个数).因为任意正整数都可以唯一表示成如下形式:
k=p1^a1*p2^a2*……*pi^ai;(即分解质因数形式)
可以推出:E(k)=(p1-1)(p2-1)……(pi-1)*(p1^(a1-1))(p2^(a2-1))……(pi^(ai-1))
               =k*(p1-1)(p2-1)……(pi-1)/(p1*p2*……pi);
               =k*(1-1/p1)*(1-1/p2)....(1-1/pk)

               = k*(p1-1)/p1   * (p2 - 1) / p2 .......

/*在程序中利用欧拉函数如下性质,可以快速求出欧拉函数的值(a为N的质因素)
若(N%a==0 && (N/a)%a==0) 则有:E(N)=E(N/a)*a;
若(N%a==0 && (N/a)%a!=0) 则有:E(N)=E(N/a)*(a-1);
*/

 

一般解法:

 

 

 1 int phi[MAX];
 2 
 3 void genPhi(int n) /* 求数组phi(i)的例程, n为最大的i+1 */
 4 {
 5 int i, j, pNum = 0 ;
 6 memset(phi, 0sizeof(phi)) ;
 7 phi[1] = 1 ;
 8 for(i = 2; i < n; i++)
 9 {
10    if(!phi[i])
11    {
12     for(j = i; j < n; j += i)
13     {
14      if(!phi[j])
15       phi[j] = j;
16      phi[j] = phi[j] / i * (i - 1);
17     }
18    }
19 }
20 }

 

 

快速求法:

 1 void init()// 素数筛选 及求 欧拉函数值
 2 {
 3     ll num = 0 ,i,j;
 4 
 5     phi[1] = 1 ;
 6 
 7     CL(f,false) ;
 8 
 9     for(i = 2 ; i <= 100000;i++)
10     {
11 
12         if(f[i] == false)
13         {
14             prim[num++] = i;
15             phi[i] = i - 1 ;
16         }
17         for(j = 0;j< num&&prim[j]*i <= 100000;j++)
18         {
19               f[i*prim[j]] = true ;
20               if(i%prim[j] == 0)
21               {
22                   phi[i*prim[j]] = phi[i] *prim[j] ;
23 
24               }
25               else
26                  phi[i*prim[j]] = phi[i]*(prim[j] - 1) ;
27 
28         }
29     }

   }

  

             poj 2478          Farey Sequence

 

http://poj.org/problem?id=2478 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<set>
 7 #include<map>
 8 #include<queue>
 9 #include<vector>
10 #include<string>
11 #define inf 0x7fffffff
12 #define maxn 1600000
13 #define CL(a,b) memset(a,b,sizeof(a))
14 #define  ll  long long
15 #define mx 1000010
16 using namespace std;
17 
18 
19 bool f[maxn] ;
20 ll phi[maxn] ;//记录欧拉函数值
21 ll prim[maxn] ;
22 ll ans[maxn] ;
23 
24 void init()// 素数筛选 及求 欧拉函数值
25 {
26     ll num = 0 ,i,j;
27 
28     phi[1] = 1 ;
29 
30     CL(f,false) ;
31 
32     for(i = 2 ; i < mx;i++)
33     {
34 
35         if(f[i] == false)
36         {
37             prim[num++] = i;
38             phi[i] = i - 1;
39         }
40         for(j = 0;j< num&&prim[j]*i < mx;j++)
41         {
42               f[i*prim[j]] = true ;
43               if(i%prim[j] == 0)
44               {
45                   phi[i*prim[j]] = phi[i] *prim[j] ;
46 
47               }
48               else
49                  phi[i*prim[j]] = phi[i]*(prim[j] - 1) ;
50 
51         }
52     }
53 
54     ans[1] = ans[0] = 0 ;
55     for(i = 2; i < mx;i++)
56        ans[i] = ans[i-1] + phi[i] ;
57 
58 
59 
60 
61 }
62 int main()
63 {
64     int n ;
65     init() ;
66 
67     while(scanf("%d",&n),n)
68     {
69 
70 
71         printf("%I64d\n",ans[n]) ;
72     }
73 }

 

 

posted @ 2012-11-24 11:00  Szz  阅读(649)  评论(0编辑  收藏  举报