1. 程式人生 > 實用技巧 >題解 SP4141 【ETF - Euler Totient Function】

題解 SP4141 【ETF - Euler Totient Function】

實際發表時間:2020-04-15
https://www.luogu.com.cn/problem/SP4141

眾所周知,尤拉函式\(φ(n)\)表示\(n\)以內與\(n\)互質的個數,所以把與\(n\)不互質的數篩掉即可

做法:

Step1:

把最後要返回的值\(res\)初始化為\(n\),以便後面篩的過程

Step2:

從2列舉到\(\sqrt{n}\),即列舉\(n\)質因數,如果\(n\%i=0\),那麼就\(res= res\times \dfrac{i-1}{i}\),篩掉\(i\)的倍數,然後\(n/=i\)直到\(n\%i\not=0\),來保證以後再也不會篩到\(i\)的倍數
\(\mathcal{Q}:\)

那怎麼保證\(i\)是質因數呢?
\(\mathcal{A}:\)因為我們已經\(n/=i\)直到\(n\%i\not=0\),\(i\)的倍數(即非質因數)不會再能去篩

Step3:

篩完後,\(n\not=1\)怎麼辦?
那麼這時候說明\(n\)就是一個質數,或者剩下的\(n\)是個大於\(\sqrt{n}\)的質因數,因為前面沒被篩掉。所以我們重複原來的操作,\(res=res \times \dfrac{n-1}{n}\)即可
\(\mathcal{Q}:\)那怎麼證明最多隻有一個大於\(\sqrt{n}\)質因數呢?
\(\mathcal{A}:\)反證法,如果有兩個大於\(\sqrt{n}\)

的質因數,那它們乘起來就會大於\(n\)

程式碼:

inline int phi(int n)
{
	int res=n;//Step1
	for(int i=2; i*i<=n; ++i)//Step2
	{
		if(n%i) continue;
		res = res/i*(i-1);
		while(!(n%i)) n /= i;
	}
	if(n>1) res = res/n*(n-1);//Step3
	return res;
}