欧拉函数

欧拉函数
欧拉函数是数论中很重要的一个函数,欧拉函数是指:对于一个正整数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 }

 

 

转载于:https://www.cnblogs.com/acSzz/archive/2012/11/24/2785538.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值