歐拉函數學習筆記
原作者:liuzibujian
原文:https://blog.csdn.net/liuzibujian/article/details/81086324
本文稍作補充,精細排版。
前言
歐拉函數聽起來很高大上,但其實非常簡單,也是NOIP裏的一個基礎知識,希望大家看完我的博客能有所理解。
數論是數學的一個分支,它只討論正整數的性質,所以以下都是針對正整數進行研究的。
什麽是歐拉函數
歐拉函數是小於\(x\)的整數中與\(x\)互質的數的個數,一般用\(\varphi(x)\)表示。特殊的,\(\varphi (1)=1\)。
如何計算歐拉函數
通式: \(\varphi(x)=x \cdot \prod_{i=1}^n{\left(1-\frac{1}{p_i}\right)},\quad\varphi(1)=1\)
其中\(p_1,p_2,\cdots, p_n\)為\(x\)的所有質因數,\(x\)是正整數。
那麽,怎麽理解這個公式呢?對於\(x\)的一個質因數\(p_i\),因為\(x\)以內\(p_i\)的倍數是均勻分布的,所以\(x\)以內有\(\frac{1}{p_i}\)的數是\(p_i\)的倍數,那麽有\(1-\frac{1}{p_i}\)的數不是\(p_i\)的倍數。再對於\(p_j\),同理,有\(1-\frac{1}{p_j}\)的數不是\(p_j\)的倍數,所以有\((1-\frac {1}{p_i})*(1-\frac {1}{p_j})\)的數既不是\(p_i\)的倍數,又不是\(p_j\)
不理解?沒關系,舉個例子。比如\(x=12\),12以內有\(\frac {1}{2}\)的數是2的倍數,那麽有\(1-\frac {1}{2}\)的數不是2的倍數(1,3,5,7,9,11),這6個數裏又有\(\frac {1}{3}\)的數是\(3\)的倍數,只剩下\((1-\frac {1}{2})*(1-\frac{1}{3})\)的數既不是2的倍數,也不是3的倍數(1,5,7,11)。這樣剩下的\(12*(1-\frac{1}{2})*(1-\frac{1}{3})\)
積性函數
先介紹一下什麽是積性函數,後面將會用到。
若當\(m\)與\(n\)互質時,\(f(m?n)=f(m)?f(n)\),那麽\(f\)是積性函數。
若對任意正整數,都有\(f(m*n)=f(m)*f(n)\)成立,則\(f\)是完全積性函數。
歐拉函數的幾個性質
1. 對於質數\(p\),\(\varphi(p)=p?1\)
因為p是質數,所以1到n-1都與n互質。
2. 若\(p\)為質數,\(x=p^k\),則\(\varphi(x)=p^k-p^{k-1}\)
\(x\)只有一個質因數\(p\),根據公式\(\varphi(x)=x\cdot\prod_{i=1}^n{\left(1-\frac{1}{p_i}\right)}=x\cdot (1-\frac{1}{p})=p^k\cdot\left(1-\frac{1}{p}\right)=p^k-p^{k-1}\)
3. 歐拉函數是積性函數,但不是完全積性函數
若\(m,n\)互質,則\(\varphi(m?n)=\varphi(m)?\varphi(n)\)。特殊的,當\(m=2\),\(n\)為奇數時,\(\varphi(2*n)=\varphi(n)\)。
\[\begin{aligned} \varphi(m)* \varphi(n) &= m*n * \prod_{i=1}^{a_m}{(1-\frac{1}{p_i})}*\prod_{i=1}^{a_n}{(1-\frac{1}{p_i})} \&= m*n * \prod_{i=1}^{a_m+a_n}{(1-\frac{1}{p_i})} \&= \varphi(m*n) \end{aligned}\]
4. 當\(n>2\)時,\(\varphi(n)\)是偶數
前幾個都可以利用公式證明,這個卻不行。
首先有一個基本事實:若\(n>m,\,\gcd(n,m)=1\),則\(\gcd(n,n-m)=1\)。直白的說,如果與\(n\)互質的數一個是\(m\),那麽還存在另一個數\(n-m\)也與n互質。
(補充:反證法,設\(\gcd(n,n-m)=k \neq 1\),則有\(a,b\in\mathbb{N}^+,\, a>b\)滿足\(n=ak,\,n-m=bk\),得\(m=(a-b)k\),不符合\(\gcd(n,m)=1\))
與\(n\)互質的數是成對出現的,所以\(\varphi(n)\)必為偶數。但還要排除\(m=n-m\)的情況:如果\(m=n-m\),即\(n=2?m\),那麽\(n>2\)時\(n,m\)必然不互質,與前提相悖,故\(m\neq n-m\)。
附上一個較為麻煩的證明
case 1:若\(n\)為質數,根據性質1,\(\varphi(n)=n-1\)必為偶數。
case 2:若\(n\)為合數,則可以寫成\(n=p_1^{k_1}p_2^{k_2}\cdots p_n^{k_n}\)(\(p_1,p_2,\cdots, p_n\)為\(n\)的質因數,\(k_1,k_2,\cdots,k_n\)為對應得指數),而歐拉函數是積性函數,\(\varphi(n)=\varphi(p_1^{k_1})\varphi(p_2^{k_2})\cdots \varphi(p_n^{k_n})\),暫且只看\(\varphi(p_1^{k_1})\),根據性質2得到\(\varphi(p_1^{k_1})=p_1^{k_1}-p_1^{k_1-1}=(p_1-1)p_1^{k_1-1}\),其中\(p_1-1\)必為偶數,偶數乘以任何數均為偶數,故\(\varphi(n)\)為偶數。
5. 小於\(n\)的數中,與\(n\)互質的數的總和為\(\varphi(n)*n/2\)(\(n>1\))
證明這個也要用到上面所說的基本事實。與\(n\)互質的數一個是\(m\),那麽還存在另一個數\(n-m\)也與\(n\)互質。所以與\(n\)互質的數的平均數是\(n/2\),而個數又是\(\varphi(n)\),可以得到這些數的和就是\(\varphi(n)*n/2\)。
6. \(n=\sum_{d|n}{\varphi(d)}\),即n的因數(包括1和它自己)的歐拉函數之和等於n
證明1(理性的證明):
這個證明起來有點麻煩。設\(F(n)=\sum_{d|n}{\varphi(d)}\)。
(1)如果\(n=1\),\(\varphi(n)=1=n\),滿足\(F(n)=n\)。
(2)如果\(n\)是質數,\(\varphi(n)=n\left(1-\frac{1}{n}\right)=n-1\),所以\(\varphi(n)+\varphi(1)=1\),滿足\(F(n)=n\)。
(3)如果\(n\)是一個質數\(p\)的冪,即\(n=p^k\),因為\(p^k\)的因數只有\(1,p,p^2,p^3,\cdots,p^k\),根據歐拉函數的性質2(\(\varphi(p^k)=p^k-p^{k-1}\)),代入計算
\(F(p^k)=\varphi(1)+\varphi(p)+\varphi(p^2)+...+\varphi(p^k)=1+(p-1)+(p^2-p)+...+(p^k-p^{k-1})=p^k\)
滿足\(F(n)=n\)。
(4)如果\(n\)有多個質因子,即\(n=p_1^{k_1}p_2^{k_2}\cdots p_n^{k_n}\)。
(4.1)首先證明\(F(n)\)是個積性函數:設\(m,n\)互質,則要證\(F(m?n)=F(m)?F(n)\)。
\[
\begin{aligned}
F(m)?F(n) &= \sum_{i|m}{\varphi(i)}*\sum_{j|n}{\varphi(j)} \ &= \varphi(i_1)*\varphi(j_1)+\varphi(i_1)*\varphi(j_2)+...+\varphi(i_1)*\varphi(j_{kn}) \ &\quad +\varphi(i_2)*\varphi(j_1)+\varphi(i_2)*\varphi(j_2)+...+\varphi(i_2)*\varphi(j_{kn}) \ &\quad +\cdots\ &\quad +\varphi(i_{km})*\varphi(j_1)+\varphi(i_{km})*\varphi(j_2)+...+\varphi(i_{km})*\varphi(j_{kn})
\end{aligned}
\]
其中\(i_1,i_2,\cdots ,i_{km}\)為\(m\)的所有因數,\(j_1,j_2,\cdots,j_{kn}\)為\(n\)的所有因數之和.
因為\(m\)與\(n\)互質,所以它們的因數也必然全都兩兩互質,而歐拉函數又是個積性函數,即\(\varphi(i_k*j_k)=\varphi(i_k)*\varphi(j_k)\),那麽上式又可以等價於\(\varphi(i_1*j_1)+\varphi(i_1*j_2)+\cdots+\varphi(i_{km}*j_{kn})\)。可以發現,\(i_1*j_1,i_1*j_2,\cdots,i_{km}*j_{kn}\)這些數構成了\(m?n\)的所有因數。那麽這些數的歐拉函數之和就等於\(F(m?n)\),所以\(F(m?n)=F(m)?F(n)\),證得F是一個積性函數。
(4.2)根據(4.1)與(3),\(n=p_1^{k_1}p_2^{k_2}\cdots p_n^{k_n}\)時,\(F(n)=F(p_1^{k_1})*F(p_2^{k_2})*\cdots*F(p_n^{k_n})=p_1^{k_1}p_2^{k_2}\cdots p_n^{k_n}=n\) 成立。
綜上,\(F(n)=n\)對所有的正整數\(n\)成立。
證明2(感性的證明):
以12為例。12的因子有1,2,3,4,6,12。把與這些數互質的數列出來:
1 :1
2 :1
3 :1 2
4 :1 3
6 :1 5
12:1 5 7 11
不妨把這些數作為分母,把與這些數互質的數作為分子,寫成分數形式:
1/1
1/2
1/3 2/3
1/4 3/4
1/6 5/6
1/12 5/12 7/12 11/12
顯然,每一行的數的個數就是該行的分母的歐拉函數值。倘若把這些數都改成以12為分母的數:
12/12
6/12
4/12 8/12
3/12 9/12
2/12 10/12
1/12 5/12 7/12 11/12
可以發現,這些數是以12為分母,1~12為分子的所有數,所以個數為12個。所以與12互質的數的歐拉函數值之和就是12。這樣,命題大概就被證明了吧。
求歐拉函數
埃拉托斯特尼篩求歐拉函數
觀察歐拉函數的公式,\(\varphi(x)=x\prod_{i=1}^n{(1-\frac{1}{p_i})}=x\prod_{i=1}^n{\frac{p_i-1}{p_i}}\)。我們用phi[x]
表示\(\varphi(x)\)。可以一開始把phi[x]
賦值為\(x\),然後每次找到它的質因數就\(phi[x]=phi[x]/p_i?(p_i?1)\)(先除再乘,避免溢出)。當然,若只要求一個數的歐拉函數,可以從1到sqrt(n)掃一遍,若\(\gcd(i,n)=1\)就更新phi[n]
。復雜度為\(O(\log n)\)(代碼就不給了)。那要求1~n所有數的歐拉函數呢?可以用埃拉托斯特尼篩的思想,每次找到一個質數,就把它的倍數更新掉。這個復雜度雖然不是\(O(n)\),但還是挺快的(據說是\(O(n*\ln \ln n)\),關於證明,可以點這裏,雖然我看不懂)。
代碼如下:
void euler(int n){
for (int i=1;i<=n;i++) phi[i]=i;
for (int i=2;i<=n;i++){
if (phi[i]==i){//這代表i是質數
for (int j=i;j<=n;j+=i){
phi[j]=phi[j]/i*(i-1);//把i的倍數更新掉
}
}
}
}
歐拉篩求歐拉函數
前提是要懂歐拉篩。每個數被最小的因子篩掉的同時,再進行判斷。i
表示當前做到的這個數,prime[j]
表示當前做到的質數,那要被篩掉的合數就是i*prime[j]
。若prime[j]
在這個合數裏只出現一次(i%prime[j]!=0
),也就是i
和prime[j]
互質時,則根據歐拉函數的積性函數的性質,phi[i * prime[j]]=phi[i] * phi[prime[j]]
。若prime[j]
在這個合數裏出現了不止一次(i%prime[j]=0
),也就是這個合數的所有質因子都在i
裏出現過,那麽根據公式,\(\varphi(i * prime[j])=prime[j] * i * \prod_{k=1}^n{(1-\frac{1}{p_k})} =\varphi(i) *prime[j]\)。復雜度為\(O(n)\)。
還是看代碼吧:
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]];//利用了歐拉函數是個積性函數的性質
}
}
}
總結
有關歐拉函數的性質,只需做個了解,而求歐拉函數的代碼,卻是一定要會寫的。這只是走進數論世界的第一步。
歐拉函數學習筆記