歐拉函數性質與求法 [數論][歐拉函數]


n的歐拉函數值用符號φ(n)表示

歐拉函數的定義是,對於一個正整數n,小於n且與n互質的數的數目(包括1,特殊地,φ(1)=1 )。

設p1,p2,p3,...,pr為n的全部r個質因數,則有φ(n)=n*(1-1/p1)*(1-1/p2)*(1-1/p3)*(1-1/p4)…..(1-1/pr)。

顯然,用這個方法來計算單個歐拉函數是可以求解的。

附上代碼:

 1 int get_phi(int x){
 2     int re=x;
 3     for(int i=2;i*i<=x;i++)
 4         if(x%i==0){
 5             re/=i;re*=i-1;
 6             while(x%i==0)
 7                 x/=i;
 8         }
 9     //仍有質因數?特判x=2及x=3的情況 
10     if(x^1) re/=x,re*=x-1;
11     return re;
12 }

這個求法的時間復雜度是O(√n)d的。

但這個求法有弊端:

* 對於大量需要計算的歐拉函數值,逐一分解n的時間復雜度顯然是十分高的。

 

在使用求解歐拉函數之前,介紹歐拉函數的幾個性質:

(1) 歐拉函數是積性函數,當正整數m,n互質時,滿足φ(mn)=φ(m)φ(n)。

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

(3) n=∑ d|n φ(d)    ( d|n )。

(4) 對於給定的一個質數p,φ(p)=p -1。則對於正整數 n = p^k ,φ(n) = p^k - p^(k -1)。

(5) 若(N % a == 0 && (N / a) mod a == 0) 則有:φ(N)=φ(N / a) * a。

(6) 若(N % a == 0 && (N / a) mod a != 0)  則有:φ(N)=φ(N / a) * (a - 1)。 (a 為質數)

 

主要利用以上性質(4)(5)(6),我們可以用遞推的方法按以下步驟來打出歐拉函數表。

(1) 記φ(1)=1。這是遞推步驟嗎。

(2) 根據性質(4),對於質數i,可直接得φ(i)=i-1,把i放入質數表prime中。

(3) 對於i,從頭開始枚舉質數(思考為什么枚舉質數),根據性質(5)(6),當(i mod primej) != 0時,φ(i*primej) = φ(i)*(primej -1)

                             當枚舉到(i mod primej) == 0時,φ(i*primej) = φ(i)*(primej),並停止(思考為什么要停止),枚舉下一個i。

由此我們得到了打出歐拉函數表的主要代碼(變量的定義不在這里展示)

 1     phi[1]=1;
 2     for(int i=2;i<=n;i++){
 3         if(!check[i]){
 4             prime[++cnt]=i;
 5             phi[i]=i-1;
 6         }
 7         for(int j=1;j<=cnt&&prime[j]*i<=n;j++){
 8             check[i*prime[j]]=1;
 9             if(i%prime[j])  phi[i*prime[j]]=phi[i]*(prime[j]-1);
10             else{
11                 phi[i*prime[j]]=phi[i]*prime[j];
12                 break;
13             }
14         }
15     }

可以簡單地得知時間復雜度是線性的O(n)。

利用打好的歐拉函數表,我們可以驗證它的以上幾個性質。


 

性質(2)

1     for(int i=n/2*2;i>1;i-=2)
2         if((i/2)&1)
3             printf("phi[%d] = %d = phi[%d/2] = phi[%d] = %d\n",i,phi[i],i,i/2,phi[i/2]);

example

 

phi[38] = 18 = phi[38/2] = phi[19] = 18
phi[34] = 16 = phi[34/2] = phi[17] = 16
phi[30] = 8 = phi[30/2] = phi[15] = 8
phi[26] = 12 = phi[26/2] = phi[13] = 12
phi[22] = 10 = phi[22/2] = phi[11] = 10
phi[18] = 6 = phi[18/2] = phi[9] = 6
phi[14] = 6 = phi[14/2] = phi[7] = 6
phi[10] = 4 = phi[10/2] = phi[5] = 4
phi[6] = 2 = phi[6/2] = phi[3] = 2
phi[2] = 1 = phi[2/2] = phi[1] = 1



性質(3)

 1     for(int i=1;i<=n;i++){
 2         printf("%d = ",i);
 3         int temp=0;
 4         int j;
 5         for(j=1;j<=i;j++)
 6             if(i%j==0){
 7                 temp+=phi[j];
 8                 printf("phi[%d]( =%d ) ",j,phi[j]);
 9                 break;
10             }
11         for(j=j+1;j<=i;j++)
12             if(i%j==0){
13                 temp+=phi[j];
14                 printf("+ phi[%d]( =%d ) ",j,phi[j]);
15             }
16         printf(" =%d\n",temp);
17     }

example

1 = phi[1]( =1 ) =1
2 = phi[1]( =1 ) + phi[2]( =1 ) =2
3 = phi[1]( =1 ) + phi[3]( =2 ) =3
4 = phi[1]( =1 ) + phi[2]( =1 ) + phi[4]( =2 ) =4
5 = phi[1]( =1 ) + phi[5]( =4 ) =5
6 = phi[1]( =1 ) + phi[2]( =1 ) + phi[3]( =2 ) + phi[6]( =2 ) =6
7 = phi[1]( =1 ) + phi[7]( =6 ) =7
8 = phi[1]( =1 ) + phi[2]( =1 ) + phi[4]( =2 ) + phi[8]( =4 ) =8
9 = phi[1]( =1 ) + phi[3]( =2 ) + phi[9]( =6 ) =9
10 = phi[1]( =1 ) + phi[2]( =1 ) + phi[5]( =4 ) + phi[10]( =4 ) =10


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM