欧拉函数小结

欧拉函数:

φ(n)表示1~n中和n互素的数目

 

要处理出欧拉函数。先证明φ(p)=p-1.(p为素数)

根据互素的概念。两个数的公约数只有1,那么这两个数互素。再根据素数的定义。公约数除了本身以外只有1的数为素数。所以得证φ(p) = p-1.

 

再证明欧拉函数为不完全积性函数。

φ(m1*m2) = φ(m1)*φ(m2) 其中 m1和m2互素。即gcd(m1,m2)=1.

证明过程在我另外一篇博文中。我觉得那种证明比较好。当然还有别的比较好的证明方法。

http://www.cnblogs.com/Milkor/p/4464515.html

 

思考一个这样的经典问题。知道一个函数是积性的(其实只要是在两个互素数中的积性)。

那么根据算术基本定理(任何一个数可以拆分成素数的乘积形式)

φ(m) = φ(p1^k1) * φ(p2^k2) * φ(p3^k3) *...

那么我们只要求出φ(p^k)就可以求出任意数的对应的欧拉函数的对应值。

 

1~p^k 一共有p^k个数。

其中是p的倍数为 <p,2p,3p...p^k> (最后那个数可以列不等式找出来)。个数为p^k/p = p^(k-1).

所以和p^k互素的数的个数为 p^k - p^(k-1).

 

那么根据上述。可得

以上便是欧拉公式的来源。

 

顺便根据我们上述的推论,我们再推导一下线性筛法欧拉函数中。

当i%j==0的时候。也就是j为i的因子的时候。

 

φ(i*j)=φ(i)*j.这个结论吧。

证明过程:

 

  1 #include<stdio.h>
  2 #include<string.h>
  3 #define N 100
  4 
  5 int primeE[N+5];
  6 int primeM[N+5];
  7 int numE;
  8 int numM;
  9 bool mark[N+5];
 10 int euler[N+5];
 11 int mobius[N+5];
 12 
 13 void Euler()
 14 {
 15     int i,j;
 16     numE = 0;
 17     memset(mark,0,sizeof(mark));
 18     euler[1] = 0;
 19     for(i=2;i<=N;i++)
 20     {
 21         if(!mark[i])
 22         {
 23             primeE[numE++] = i;
 24             euler[i]=i-1;
 25         }
 26         for(j=0;j<numE;j++)
 27         {
 28             if(i*primeE[j]>N){break;}
 29             mark[i*primeE[j]] = 1;
 30             if(i%primeE[j]==0)
 31             {
 32                 euler[i*primeE[j]] = euler[i]*primeE[j];
 33                 break;
 34                 /*
 35                 原理:例如要构造24
 36                 3*8 = 24 = 2*12
 37                 8中有2的因子。8拆分成2*i. 把i给3 一定可以构造出最小的质因子。
 38                 把一个合数当做最小质因子*另外一个数 来处理。     
 39                 */
 40             }
 41             else
 42             {
 43                 euler[i*primeE[j]] = euler[i]*euler[primeE[j]];
 44             }
 45         }
 46     }
 47 }
 48 void Mobius()
 49 {
 50     int i,j;
 51     numM = 0;
 52     memset(mark,0,sizeof(mark));
 53     mobius[1] = 1;
 54     for(i=2;i<=N;i++)
 55     {
 56         if(!mark[i])
 57         {
 58             primeM[numM++] = i;
 59             mobius[i] = -1;
 60         }
 61         for(j=0;j<numM;j++)
 62         {
 63             if(i*primeM[j]>N){break;}
 64             mark[i*primeM[j]] = 1;
 65             if(i%primeM[j]==0)
 66             {
 67                 mobius[i*primeM[j]] = 0;
 68                 break;
 69             }
 70             else
 71             {
 72                 mobius[i*primeM[j]] = -mobius[i];
 73             }
 74         }
 75     }
 76 }
 77 int main()  
 78 {  
 79     Euler();
 80     Mobius();
 81     int i;
 82     for(i=0;i<numE;i++)
 83     {
 84         printf("%d ",primeE[i]);
 85     }
 86     printf("\n");
 87     for(i=0;i<numM;i++)
 88     {
 89            printf("%d ",primeM[i]);
 90     }
 91     printf("\n");
 92     for(i=1;i<=N;i++)
 93     {
 94         printf("%d=%d ",i,euler[i]);
 95     }
 96     printf("\n");
 97     for(i=1;i<=N;i++)
 98     {
 99         printf("%d=%d ",i,mobius[i]);
100     }
101 }
欧拉函数线性筛和莫比乌斯函数线性筛

 

posted @ 2015-05-02 03:02  Milkor  阅读(585)  评论(0编辑  收藏  举报