欧拉函数

欧拉函数的定义:1到N中与N互质的数的个数被称为欧拉函数,记做F(N)。

若N=p1^c1*p2^c2*.........*pm^cm。(pi为质数)

那F(N)=N*(p1-1)/p1*(p2-1)/p2*.......*(pm-1)/pm

证明:设p是N的质因子,1到N中p的倍数有p,2*p,3*p,......(N/p)*p,一共N/p个。同理,

  如果q也是N的质因子,那1到N中q的倍数也有N/q个。如果把N/p+N/q个数去掉,那

  根据容斥原理可知,p*q的倍数被排除了两次,需要加回来一次,所以1到N中不与N

  含有共同质因子p或q的数的个数为:

            N-(N/p)-(N/q)+N/(p*q)=N*(1-1/p-1/q+1/(p*q))=N*(1-1/p)*(1-1/q);

根据欧拉函数的计算式,我们只需要分解质因数便可求出欧拉函数。

int phi(int n)
{
    int ans=n;
    for(int i=2;i<=sqrt(n);i++)
    {
        if(n%i==0)//i是素数
        {
            ans=ans/i*(i-1);
            while(n%i==0)
                n/=i;
        }
    }
    if(n>1)
        ans=ans/n*(n-1);
    return ans;
}

关于欧拉函数的一些性质:

  对于所有的n>1,1到n中与n互质的数的和为n*F(n)/2;

  如果a,b互质,则F(a*b)=F(a)*F(b);

  设p为质数,如果n%p==0&&n%(p*p)==0,那么F(n)=F(n/p)*p;

  设p为质数,如果n%p==0&&n%(p*p)!=0,那么F(n)=F(n/p)*(p-1);

求2到n中每个数的欧拉函数:

  可以利用素筛并按照欧拉函数的计算式,可以在O(N*logN)的时间内求出2到n中每个数的欧拉函数。

void euler(int n)
{
    for(int i=2;i<=n;i++)
        phi[i]=i;
    for(int i=2;i<=n;i++)
    {
        if(phi[i]==i)
        {
            for(int j=i;j<=n;j+=i)
                phi[j]=phi[j]/i*(i-1);
        }
    }
}

  利用线性筛和欧拉函数的一些性质可以在O(N)的时间复杂度内求出2到n里的欧拉函数。

int v[maxn],prime[maxn],phi[maxn];
void euler(int n)
{
    memset(v,0,sizeof(v));//最小质因子
    m=0;//质数的数量
    for(int i=2;i<=n;i++)
    {
        if(v[i]==0)//i是质数
        {
            v[i]=i;
            prime[++m]=i;
            phi[i]=i-1;
        }
        //给当前的数i乘上一个质因子
        for(int j=1;j<=m;j++)
        {
            if(prime[j]>v[i]||prime[j]>n/i)
                break;
            //prime[j]是合数i*prime[j]的最小质因子
            v[i*prime[j]]=prime[j];
            if(i%prime[j])
                phi[i*prime[j]]=phi[i]*(prime[j]-1);
            else
                phi[i*prime[j]]=phi[i]*prime[j];
        }
    }
}
原文地址:https://www.cnblogs.com/zcb123456789/p/12601643.html