關於歐拉函數:ios
定義:svg
φ(n)表示1~n中與n互質的數的個數;函數
求法:spa
已知n的標準分解式爲:code
(哦對了,這裏全部的因子都是質因子)blog
那麼
ci
而後求歐拉函數的兩種方法:it
1.按照定義暴力求解:io
int phi(int n){ int ret=n; for(int i=2;i*i<=n;i++){ if(n%i==0){ ret-=ret/i; while(n%i==0) n/=i; } } if(n>1) ret-=ret/n; return ret; }
解釋一下:class
對於歐拉函數φ來講,咱們每*(1-1/pn),就至關於在原數的基礎上減掉原數*1/pn(這裏的原數並非指n,而是指n*某些數以後的數),假設原數爲ret,那麼咱們將ret*(1-1/pz)的值就至關於ret-ret*1/pz,由此咱們得出了ret-=ret/i;而後將n中的全部i通通除掉,防止出現再算一次的可涼(就是很涼)狀況。最後,若是n>1,說明咱們還有一個因子沒有枚舉到,此時n就是當前因子,用上方式子再減一下就行了;
2.歐拉篩時順帶着求出來了???
而後歐拉篩的話,能夠求到的值比較小,若是單純求φ的話,不如用定義呢
#include<iostream> #include<cstdlib> #include<algorithm> #include<ctime> using namespace std; int n,cnt,maxx; int prime[10000010],phi[10000010]; bool not_[10000010]; void shai(){ for(int i=2;i*i<=100000000;i++){ if(!not_[i]) { prime[++cnt]=i; phi[i]=i-1; } for(int j=1;j<=cnt&&i*prime[j]<=n;j++){ not_[i*prime[j]]=1; if(i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j]; break; } else phi[i*prime[j]]=phi[i]*phi[prime[j]]; } } } int main(){ freopen("data.in","r",stdin); freopen("data.ans","w",stdout); cin>>n; shai(); printf("%d",phi[n]); }
end-