線性篩尤拉函式
阿新 • • 發佈:2019-01-28
概念:對正整數n,尤拉函式是小於等於n的數中與n互質的數的數目。
性質: 若整數a與b(不) 互質,a+b依然與b(不)互質。
1. 如果i mod p = 0, 那麼phi(i * p)=phi(i) * p
2. 如果i mod p ≠ 0, 那麼phi(i * p)=phi(i) * (p-1)
(其中p是質數)
證明:
[1,i ]中與i不互質的數是i-phi(i)個,[1,i*p]中是i*p-p*phi(i)個,
又i與i*p沒有不同的因數,顧[1,i*p]中與i*p不互質的也是i*p-p*phi(i)個,即(1)證;
因 i mod p !=0且p為質數, 所以i與p互質,
由性質3得phi(i * p)=phi(i) * phi(p),即(2)證;
另一種形式:
若(N%p==0 && (N/p)%p==0))則有:phi[N]=phi[N/p]*p
若(N%p==0 && (N/p)%p !=0))則有:phi[N]=phi[N/p]*(p-1)
(其中p是質數)
3. 若a b互質,則 φ(a*b) =
φ(a) *
φ(b)
4. 若 n 是質數 p 的 k 次冪,則
φ(n) = (p-1)*p^(n-1)
尤拉定理:
對任何兩個互質的正整數a, m有 a^φ(m) ≡ 1(mod m)
費馬小定理:
在尤拉定理裡m取素數p時,有 a^(p-1) ≡ 1(mod p)
打表法:
非打表法:
int prime[maxn],phi[maxn]; int cnt=0; bool flag[maxn]; void get_phi(){ memset(flag,false,sizeof(flag)); phi[1]=1; for(int i=2;i<maxn;i++){ if(!flag[i]){ prime[cnt++]=i; phi[i]=i-1; } for(int j=0;i*prime[j]<maxn;j++){ flag[i*prime[j]]=true; if(i%prime[j]==0){ phi[i*prime[j]]=phi[i]*prime[j]; break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1); } } }
非打表法:
int phi(int n){
int ans=1;
for(int i=2;i*i<=n;i++){ // 可以的話這裡換成質數表更佳
if(n%i==0){
n/=i;
ans*=i-1;
while(n%i==0){
n/=i;
ans*=i;
}
}
}
if(n>1) ans*=n-1;
return ans;
}