对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目,它又称为Euler’s totient function、φ函数、欧拉商数等。 例如φ(8)=4,因为1,3,5,7均和8互质,特殊的(φ(1)=1)。
1.根据欧拉函数公式:euler(x) = x*(1-1/p1)(1-1/p2)……(1-1/pn),p为x的质因数。用公式法求解代码
int euler(int n){ int res=n,a=n; for(int i=2;i*i<=a;i++){ if(a%i==0){ res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出 while(a%i==0) a/=i; } } if(a>1) res=res/a*(a-1); return res; }
2.O(n^2)的筛法:
#include<cstdio> const int N = 100000 + 5; int phi[N]; void Euler(){ phi[1] = 1; for(int i = 2; i < N; i ++){ if(!phi[i]){ for(int j = i; j < N; j += i){ if(!phi[j]) phi[j] = j; phi[j] = phi[j] / i * (i-1); } } } } int main(){ Euler(); }
3.线性筛法(最快):
#include<iostream> #include<cstdio> #define N 40000 using namespace std; int n; int phi[N+10],prime[N+10],tot,ans; bool mark[N+10]; void getphi() { int i,j; phi[1]=1; for(i=2;i<=N;i++)//相当于分解质因式的逆过程 { if(!mark[i]) { prime[++tot]=i;//筛素数的时候首先会判断i是否是素数。 phi[i]=i-1;//当 i 是素数时 phi[i]=i-1 } for(j=1;j<=tot;j++) { if(i*prime[j]>N) break; mark[i*prime[j]]=1;//确定i*prime[j]不是素数 if(i%prime[j]==0)//接着我们会看prime[j]是否是i的约数 { phi[i*prime[j]]=phi[i]*prime[j];break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1);//其实这里prime[j]-1就是phi[prime[j]],利用了欧拉函数的积性 } } } int main() { getphi(); }