1. 程式人生 > >簡單複習一下尤拉函式

簡單複習一下尤拉函式

尤拉函式是用來求小於nn的正整數中與n互質的數的數目,用希臘字母φ(n)φ(n)表示。

對於常規求小於nn的正整數中與nn互質的數的數目,可以將小於nn的數全部用gcdgcd掃一遍,但是一次gcdgcd的時間複雜度是O(logb)O(logb),用gcdgcdφφ的時間複雜度便是O(nlogb)O(nlogb),而實際上我們可以實現時間複雜度O(n)O(n)的做法。

首先給出φ(n)φ(n)的通項公式:

顯然,任何一個大於1的正整數n可以分解為: n=p1q1p2q2...pkqkn=p_1^{q_1}*p_2^{q_2}*...*p_k^{q_k}

其中,p1,p2...pkp_1,p_2...p_knn的素數因子, 那麼,φ(n)=ni=1k(111pi)φ(n)=n*\prod_{i=1}^k(1-1\frac{1}{p_i})

接下來我們推導一下。

第一種情況:

如果n=1n=1,顯然: φ(1)=1φ(1)=1 第二種情況:

如果nn是質數,顯然: φ(n)=n1φ(n)=n-1

第三種情況:

如果nn是一個質數的某一個次方,即(pp為質數,kk為大於等於1

1的整數) n=pkn=p^k

那麼: φ(n)=φ(pk)=pkpk1=pk(11p)φ(n)=φ(p^k)=p^k-p^{k-1}=p^k(1-\frac{1}{p})

例如: φ(27)=φ(33)=3332=33(113)=18φ(27)=φ(3^3)=3^3-3^2=3^3(1-\frac{1}{3})=18

第四種情況:

如果nn可以分解為兩個互質的整數之積,即:(p1,p2p_1,p_2為質數) n=p1p2n=p_1*p_2

=p1p2

則: φ(n)=φ(p1p2)=φ(p1)φ(p2)φ(n)=φ(p_1*p_2)=φ(p_1)*φ(p_2)

也就是素數乘積的尤拉函式等於各個素數的尤拉函式的乘積。

最後,也就得到我們最後的終點,第五種情況:

對於任意大於11的正整數nn,都可以寫成一系列質數的乘積: n=p1k1p2k2p3k3...pqkqn=p_1^{k_1}*p_2^{k_2}*p_3^{k_3}*...*p_q^{k_q}

那麼根據第四種情況得到:

φ(n)=i=1qφ(piki)φ(n)=\prod_{i=1}^qφ(p_i^{k_i})

再根據第三種情況得到:

φ(n)=p1k1p2k2...pqkq(11/p1)(11/p2)...(11/pq)φ(n)=p1^k1*p2^k2*...*pq^kq*(1-1/p1)*(1-1/p2)*...*(1-1/pq)

顯然最後得到我們想要的結果:

φ(n)=ni=1q(11pi)φ(n)=n*\prod_{i=1}^q(1-\frac{1}{p_i}) 以上就是對於尤拉函式通項φ的推導,接下來讓我們看看程式碼的實現:

int euler(int n) {
	int ans=n,a=n;
	
	for(int i=2;i*i<=a;i++) if(a%i==0) {
		ans=ans/i*(i-1);
		while(a%i==0) a/=i;
	}
	
	if(a>1) ans=ans/a*(a-1);
	
	return ans;
}