基礎
- 歐拉函數phi(x)是指從1…x與x互質的自然數的個數
- 性質1:如果p是質數,phi(p)=p-1,phi(p^k)=p^k-p^(k-1)
- 性質2:如果p,k互質,phi(p*k)=phi(p)*phi(k)
然後就得到了百度百科的那個通式:
phi(x)=x*(1-1/p1)…(1-1/pn);
所以任何一個數,只需要分解質因數,把每個p^k都乘起來就是這個數的歐拉函數值了。在C++中這樣表達:
int phi(int n){
int m=(int)sqrt(n+0.5);//篩質數的上界
int ans=n;
for(int i=2;i<=m;i++) if(n&i==0){//找到n的質因數i
ans=ans/i*(i-1);
while(n%i==0) n/=i;//一直把n除到沒有因數i爲止
}
if(n>1) ans=ans/n*(n-1);//phi(1)=1,so...
return ans;
}
篩法:
int phi_table(int n){
for(int i=1;i<=n;i++) phi[i]=0;
phi[1]=1;//特別定義
for(int i=2;i<=n;i++)
if(!phi[i]){
for(int j=1;j<=n;j+=i){
if(!phi[j]) phi[j]=j;
phi[j]=phi[j]/i*(i-1);
}
}
}
奇技淫巧的應用
- 不大於x的與x互質的數和爲phi(x)*x/2
例題整理
- 法雷級數由一系列不能約分的分數按遞增的順序排列組成,現在讓你求出第n項法雷級數包含多少個分數。
- 讓找出從(0,0)點出發到(n,n)點之間只經過兩點的直線的數目。
- 對於給定的整數L,找出L能整除最短的全8序列的長度,做爲Bob的幸運數字。
- 記P_i表示正整數i的質因數集合.
已知正整數n,求滿足下列條件的有序正整數對(a,b)的數目:
(1)1<=a<=b<=n;
(2)t爲a,b的最大公約數,P_t是P_n的子集. - POJ 3696(文章裏面說的“歐拉公式”實際上指歐拉定理:a^phi(m)≡1(mod m),所以同餘方程a^x≡1(mod m)的解一定是phi(m)的因數)
- [HDU 2588] 計算1~n中有多少個數和n的最大公因數比m大(將n分解爲a*b,如果gcd(n,x)=a那麼x=a*d,其中d是一個比b小的與b互質的數。所以確定了a過後phi(b)就是x的個數了,從m開始(或者從sqrt(n)開始,看哪個更小)枚舉)
好難啊!完全不會!