歐拉函數的三種基本寫法

 概念梳理:  

     歐拉函數是少於或等於n的數中與n互質的數的數目。 

     歐拉函數的性質:它在整數n上的值等於對n進行素因子分解後,所有的素數冪上的歐拉函數之積。

     歐拉函數的值  通式:φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn),其中p1, p2……pn爲x的所有質因數,x是不爲0的整數。φ(1)=1(唯一和1互質的數(小於等     於1)就是1本身)。 (注意:每種質因數只一個。比如12=2*2*3那麼φ(12)=12*(1-1/2)*(1-1/3)=4)

    推論:當n爲奇數時,有φ(2n)=φ(n)。

    若n是質數p的k次冪,φ(n)=p^k-p^(k-1)=(p-1)p^(k-1),因爲除了p的倍數外,其他數都跟n互質。

    設n爲正整數,以 φ(n)表示不超過n且與n互素的正整數的個數,稱爲n的歐拉函數值,這裏函數φ:N→N,n→φ(n)稱爲歐拉函數。

    歐拉函數是積性函數——若m,n互質,φ(mn)=φ(m)φ(n)。

    特殊性質:當n爲奇數時,φ(2n)=φ(n), 證明與上述類似。

  算法實現與分析:

   求解歐拉函數的值可用φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn),容易知道要對n進行素因子分解。

    (1)直接實現   題目

int oula(int n)
{
    int rea=n;
    for(int i=2; i<=n; i++)
        if(n%i==0)//第一次找到的必爲素因子
        {
            rea=rea/i*(i-1);
            do
                n/=i;//把該素因子全部約掉
            while(n%i==0);
        }
    return rea;
}

這個函數的複雜度爲O(n),如果n達到1000000000,肯定會超時,由於任何一個合數都至少有一個不大於根號n的素因子,所以只需遍歷到根號n即可,這樣複雜度降爲O(√¯n)

    下面是優化代碼:

int oula(int n)
{
    int rea=n;
    for(int i=2; i*i<=n; i++)
        if(n%i==0)//第一次找到的必爲素因子
        {
            rea=rea/i*(i-1);
            do
                n/=i;//把該素因子全部約掉
            while(n%i==0);
        }
    if(n>1)
        rea=rea-rea/n;
    return rea;
}

(2)素數表實現

    先把50 000以內的素數用篩選法選出來並保存,以方便歐拉函數使用,這樣,在不考慮篩選法的時間複雜度,而單純看歐拉函數,其複雜度爲O(x),x爲O(√¯n)以內素數的個數。

bool boo[50000];
int p[20000];
void prim()
{
    memset(boo,0,sizeof(boo));
    boo[0]=boo[1]=1;
    int k=0;
    for(int i=2; i<50000; i++)
    {
        if(!boo[i])
            p[k++]=i;
        for(int j=0; j<k&&i*p[j]<50000; j++)
        {
            boo[i*p[j]=1;
                if(!(i%p[j]))
                break;
        }
}
}//篩選法打表
int phi(int n)
{
    int rea=n;
    for(int i=0; p[i]*p[i]<=n; i++)//對於一些不是素數的可不遍歷
        if(n%p[i]==0)
        {
            rea=rea-rea/n;
            do
                n/=p[i];
            while(n%p[i]==0);
        }
    if(n>1)
        rea=rea-rea/n;
    return rea;
}

(3)遞推求歐拉函數   題目

     如果頻繁的使用歐拉函數值,就需要預先打表,下面介紹遞推求歐拉公式的方法。

    可預先之所有數的歐拉函數值都爲她本身,有定理可知,如果p是一個正整數且滿足φ(p)=p-1;那麼p是素數,在遍歷過程中如果遇到歐拉函數與自身相等的情況。那麼說明該數爲素數,把這個數的歐拉函數值改變,同時也把能被素因子整除的數改變。

for(i=1; i<=maxn; i++)
    p[i]=i;
for(i=2; i<=maxn; i+=2)
    p[i]/=2;
for(i=3; i<=maxn; i+=2)
    if(p[i]==i)
    {
        for(j=i; j<=maxn; j+=i)
            p[j]=p[j]/i*(i-1);
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章