一、概念
互質關系
如果兩個整數(或者兩個以上的整數)的最大公約數是1,則稱他們為互質。也就是說兩個整數,除了1以外,沒有其它的最大公約數了,這兩個整數就叫做互質關系。
比如說7,11他們的最大公約數只有1,所以他們互質;8,10他們的最大公約數為1,2,所以這兩數不是互質關系。
歐拉函數
歐拉函數φ(n)是小於或等於n的正整數中與n互質的數的數目,稱為歐拉函數
比如說當n=8時,與8能形成互質關系的數有4個,分別是1,3,5,7,所以φ(8)=4
具體φ(n)函數的計算公式,可以分為以下四種情況:
情況一: 當n=1,φ(1)=1
因為1與任何整數都是互質關系,所以當n=1時,φ(1)=1
情況二:當n為質數,φ(n)=n-1
因為質數與小於它的每一個數,都構成互質關系,所以當n為質數時,φ(n)=n-1 。
比如說n=3時,1,2都跟他是互質關系, n=7時,1,2,3,4,5,6都跟他是互質關系。
情況三:n = p^k (p為質數,k為指數,且大於等於1),n是質數的k次方,則φ(p^k) = p^k - p^(k-1) = p^k(1 - 1/p)
比如:φ(8) = φ(2^3) = 2^3 - 2^2 = 4
φ(27) = φ(3^3) = 3^3(1 - 1/3) = 18
情況四: n是兩個互質的整數之積,如:n = p1 * p1,則 φ(n) = φ(p1p2) = φ(p1)φ(p2)
比如:φ(56)=φ(8×7)=φ(8)×φ(7)=4×6=24
二、定理
同余定理
給定一個正整數n,如果兩個整數a和b滿足a-b能夠被n整除,即(a-b)/n得到一個整數,那么就稱整數a與b對模n同余,記作a≡b(mod n)。這就是同余定理。
例如:26≡2(mod 12), 26%12 余2, 2%12余2, 26-2/12 = 0,所以26與2對模12同余
歐拉定理
在數論中,歐拉定理是一個關於同余的性質。歐拉定理表明,若n,a為正整數,且n,a互素(即),則

即與1在模n下同余;
為歐拉函數。
首先看一個基本的例子。令a = 3,n = 5,這兩個數是互素的。比5小的正整數中與5互素的數有1、2、3和4,所以。計算:
,而
。與定理結果相符。
這個定理可以用來簡化冪的模運算。比如計算的個位數,實際是求
被10除的余數。7和10互素,且
。由歐拉定理知
。所以
//歐拉函數φ(n)的作用就是把ap表示成aφ(n)*x+y
一般地,在簡化冪的模運算的時候,(當a和n互素) 我們要對a的指數取模:
當,則
。
三、求歐拉函數
一、直接法
原理:
Euler函數表達通式:euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn),其中p1,p2……pn為x的所有素因數,x是不為0的整數。euler(1)=1(唯一和1互質的數就是1本身)。
//直接法 int euler(int n) { int res=n,a=n; for(int i=2;i*i<=a;i++) { if(a%i==0) { res=res/i*(i-1); while(a%i==0) a=a/i; } } if(a>1) res=res/a*(a-1); return res; }
二、歐拉篩選法
void euler(int n) { phi[1]=1;//1要特判 for (int i=2;i<=n;i++) { if (flag[i]==0)//這代表i是質數 { prime[++num]=i; phi[i]=i-1; } for (int j=1;j<=num&&prime[j]*i<=n;j++)//經典的歐拉篩寫法 { flag[i*prime[j]]=1;//先把這個合數標記掉 if (i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j];//若prime[j]是i的質因子,則根據計算公式,i已經包括i*prime[j]的所有質因子 break;//經典歐拉篩的核心語句,這樣能保證每個數只會被自己最小的因子篩掉一次 } else phi[i*prime[j]]=phi[i]*phi[prime[j]];//利用了歐拉函數是個積性函數的性質 } } }
三、另一種更簡潔的篩選法、推薦
const int maxn = 1e6+10; int prim[maxn], w[maxn], cnt = 0;//prim[i]起標記作用,prim[i]==0表示i是質數,注意這里把1也標記成了質數 int x[maxn];//x[i]表示偶數是i的符合條件的兩個質數是x[i]和i-x[i]; void init() { memset(prim, false, sizeof(prim)); prim[1]=1;//1不是素數 for(int i = 2; i < maxn; i++) { if(prim[i]) //判斷i是否為偶數 continue; w[cnt++] = i;//w存質數 for(int j = i << 1; j < maxn; j+=i)//把所有質數的倍數標記 prim[j] = true; } }
歐拉公式的延伸:小於n的且與n互質的數的和是euler(n)*n/2
來源:CSDN
原文:https://blog.csdn.net/u012861385/article/details/24271435
來源:簡書