欧拉函数:给定一个正整数n,在小于等于n的数中,与n互质的数的个数。

关于欧拉函数,有以下几个规律:

  1.当n为质数时,euler(n)=n-1.

  2.当p与q互质时,euler(p*q)=euler(p)*euler(q).

  3.当n等于p^k时,p为质数,euler(n)=p^k-p^(k-1).

对于任意的n,有n=p1^m1*p2^m2*p3^m3……*pk^mk; p1……pk为质数,所以p1^m1……pk^mk都互质

所以euler(n)=euler(p1^m1)*euler(p2^m2)……*euler(pk^mk)

由于规律3,euler(p^k)=(p-1)*p^(k-1)

推理可得:euler(n)=n*(1-1/p1)*(1-1/p2)……*(1-1/pk)

 

算法实现:利用质因数分解,分解出质因数组合,套用公式即可。

int euler(int n){
    int res=n;
    for(int i=2;i<n;i++){
        if(n%i==0){
            res=res/i*(i-1);
            while(n%i==0)n/=i;
        }
    }
    if(n!=1)res=res/n*(n-1);
    return res;
} 

 

如何求解1到n里的每个数的欧拉函数,显然对每个数都跑一遍欧拉函数时非常慢的。

我们可以利用euler(p*q)=euler(p)*euler(q),通过前面已经计算出来的值,推导后面的值。

可以使用线性筛/欧拉筛O(n),在计算n以内的质数的同时,计算n以内的欧拉函数。

const int maxn=100009;
int phi[maxn+1];                //phi[i]表示i的欧拉函数 
int prime[maxn+1];                //prime[0]用来储存素数个数 
void getPrime()
{
    memset(prime,0,sizeof(prime));
    for(int i=2;i<=maxn;i++){
        if(!prime[i])prime[++prime[0]]=i,phi[i]=i-1;
        for(int j=1;j<=prime[0]&&prime[j]*i<=maxn;j++){
            prime[prime[j]*i]=1;
            if(i%prime[j]==0){
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            phi[i*prime[j]]=phi[i]*phi[prime[j]];
        }
    }
}

 

posted on 2020-04-18 10:27  新望  阅读(251)  评论(0编辑  收藏  举报