1. 程式人生 > >歐拉函數知識點總結及代碼模板及歐拉函數表

歐拉函數知識點總結及代碼模板及歐拉函數表

算法實現 for 表示 滿足 情況 += radi 分析 因子

歐拉函數是少於或等於n的數中與n互質的數的數目。

歐拉函數的性質:它在整數n上的值等於對n進行素因子分解後,所有的素數冪上的歐拉函數之積。

歐拉函數的值  通式:φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn),其中p1, p2……pn為x的所有質因數,x是不為0的整數。φ(1)=1(唯一和1互質的數(小於等 於1)就是1本身)。 (註意:每種質因數只一個。比如12=2*2*3那麽φ(12)=12*(1-1/2)*(1-1/3)=4)

推論:當n為奇數時,有φ(2n)=φ(n)。

若n是質數p的k次冪,φ(n)=p^k-p^(k-1)=(p-1)p^(k-1),因為除了p的倍數外,其他數都跟n互質。 設n為正整數,以 φ(n)表示不超過n且與n互素的正整數的個數,稱為n的歐拉函數值,這裏函數φ:N→N,n→φ(n)稱為歐拉函數。 歐拉函數是積性函數——若m,n互質,φ(mn)=φ(m)φ(n)。 特殊性質:當n為奇數時,φ(2n)=φ(n), 證明與上述類似。 算法實現與分析: 求解歐拉函數的值可用φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn),容易知道要對n進行素因子分解。 (1)直接實現
  int oula(int n)
  {
      int rea=n;
      for(int i=2; i<=n; i++)
          if(n%i==0)//第一次找到的必為素因子
          {
              rea=rea-rea/i;
              do
                  n/=i;//把該素因子全部約掉
             while(n%i==0);
         }
     return rea;
 }

這個函數的復雜度為O(n),如果n達到1000000000,肯定會超時,由於任何一個合數都至少有一個不大於根號n的素因子,所以只需遍歷到根號n即可,這樣復雜度降為O(√¯n)

下面是優化代碼:

  int oula(int n)
  {
      int rea=n;
      for(int i=2; i*i<=n; i++)
          if(n%i==0)//第一次找到的必為素因子
          {
              rea=rea-rea/i;
              do
                  n/=i;//把該素因子全部約掉
             while(n%i==0);
         }
     if(n>1)
         rea=rea-rea/n;
     return rea;
 }

(2)素數表實現

先把50 000以內的素數用篩選法選出來並保存,以方便歐拉函數使用,這樣,在不考慮篩選法的時間復雜度,而單純看歐拉函數,其復雜度為O(x),x為O(√¯n)以內素數的個數。

技術分享
  bool boo[50000];
  int p[20000];
  void prim()
  {
      memset(boo,0,sizeof(boo));
      boo[0]=boo[1]=1;
      int k=0;
      for(int i=2; i<50000; i++)
      {
         if(!boo[i])
             p[k++]=i;
         for(int j=0; j<k&&i*p[j]<50000; j++)
         {
             boo[i*p[j]=1;
                 if(!(i%p[j]))
                 break;
         }
 }
 }//篩選法打表
 int phi(int n)
 {
     int rea=n;
     for(int i=0; p[i]*p[i]<=n; i++)//對於一些不是素數的可不遍歷
         if(n%p[i]==0)
         {
             rea=rea-rea/n;
             do
                 n/=p[i];
             while(n%p[i]==0);
         }
     if(n>1)
         rea=rea-rea/n;
     return rea;
 }

(3)遞推求歐拉函數

如果頻繁的使用歐拉函數值,就需要預先打表,下面介紹遞推求歐拉公式的方法。

可預先之所有數的歐拉函數值都為她本身,有定理可知,如果p是一個正整數且滿足φ(p)=p-1;那麽p是素數,在遍歷過程中如果遇到歐拉函數與自身相等的情況。那麽說明該數為素數,把這個數的歐拉函數值改變,同時也把能被素因子整除的數改變。

  for(i=1; i<=maxn; i++)
      p[i]=i;
  for(i=2; i<=maxn; i+=2)
      p[i]/=2;
  for(i=3; i<=maxn; i+=2)
      if(p[i]==i)
      {
          for(j=i; j<=maxn; j+=i)
              p[j]=p[j]/i*(i-1);
     }

噶嗚~附上歐拉函數表:

2-100歐拉函數表 n φ(n) 2 1 3 2 4 2 5 4 6 2 7 6 8 4 9 6 10 4 11 10 12 4 13 12 14 6 15 8 16 8 17 16 18 6 19 18 20 8 21 12 22 10 23 22 24 8 25 20 26 12 27 18 28 12 29 28 30 8 31 30 32 16 33 20 34 16 35 24 36 12 37 36 38 18 39 24 40 16 41 40 42 12 43 42 44 20 45 24 46 22 47 46 48 16 49 42 50 20 51 32 52 24 53 52 54 18 55 40 56 24 57 36 58 28 59 58 60 16 61 60 62 30 63 36 64 32 65 48 66 20 67 66 68 32 69 44 70 24 71 70 72 24 73 72 74 36 75 40 76 36 77 60 78 24 79 78 80 32 81 54 82 40 83 82 84 24 85 64 86 42 87 56 88 40 89 88 90 24 91 72 92 44 93 60 94 46 95 72 96 32 97 96 98 42 99 60 100 40

歐拉函數知識點總結及代碼模板及歐拉函數表