【转】欧拉函数

链接:http://www.cnblogs.com/yefeng1627/archive/2013/01/02/2842492.html

 

欧拉函数直接计算公式

  欧拉函数的定义: E(N)= (  区间[1,N-1] 中与 N 互质的整数个数).

  对于 积性函数 F(X*Y),当且仅当 GCD(X,Y)= 1 时, F(X*Y) = F(X)* F(Y)

  任意整数可因式分解为如下形式:

        其中( p1, p2 ... pk 为质数, ei 为次数 )  

  所以

    

  因为 欧拉函数 E(X)为积性函数, 所以

     

  对于    , 我们知道 因为pi 为质数,所以 [ 1, pi-1 ] 区间的数都与 pi 互质

  对于 区间[ 1,   ]  ,共有  个数, 因为  只有一个质因子,

  所以与  约数大于1 的必定包含 质因子   , 其数量为   

  

    所以      

  又 E(N)为积性函数,所以可得 :

    

  又因为       其中( p1, p2 ... pk 为质数, ei 为次数 )  

         但是此计算公式,除法过多,所以计算速度较慢

 

  在程序中利用欧拉函数如下性质,可以快速求出欧拉函数的值 ( P为N的质因子 )

    若(N%P==0 && (N/P)%P==0) 则有:E(N)=E(N/P)*P;
 
    若(N%P==0 && (N/P)%P!=0) 则有:E(N)=E(N/P)*(P-1);

 

求单个数的欧拉函数:

long long eular(long long n)
{
    int i;
    long long ans=n;
    for(i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            ans-=ans/i;
            while(n%i==0)
                n/=i;
        }
    }
    if(n>1)ans-=ans/n;
    return ans;
}

筛法欧拉函数:

int eular[MAXN+1];
void getEular()
{
    int i,j;
    memset(eular,0,sizeof(eular));
    eular[1]=1;
    for(i=2;i<=MAXN;i++)
    {
        if(!eular[i])
            for(j=i;j<=MAXN;j+=i)
            {
                if(!eular[j])
                    eular[j]=j;
                eular[j]=eular[j]/i*(i-1);
            }
    }
}

线性筛(同时得到欧拉函数和素数表)

bool check[MAXN+10];
int phi[MAXN+10];
int prime[MAXN+10];
int tot;
void phi_and_prime_table(int N)
{
    int i,j;
    memset(check,false,sizeof(check));
    phi[1]=1;
    tot=0;
    for(i=2;i<=N;i++)
    {
        if(!check[i])
        {
            prime[tot++]=i;
            phi[i]=i-1;
        }
        for(j=0;j<tot;j++)
        {
            if(i*prime[j]>N)break;
            check[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);
        }
    }
}

  

posted @ 2016-08-13 18:33  vwqv  阅读(315)  评论(0编辑  收藏  举报