1. 程式人生 > 實用技巧 >尤拉函式

尤拉函式

尤拉函式的簡介與性質

  • 尤拉函式是少於或等於\(n\)的數中與\(n\)互質的數的數目。

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

尤拉函式的值

  • 通式:\(\varphi(x)=x(1-\frac{1}{p_1})(1-\frac{1}{p_2})(1-\frac{1}{p_3})(1-\frac{1}{p_4})\dots(1-\frac{1}{p_n})\),其中\(p1, p2\dots pn\)\(x\)的所有質因數,\(x\)是不為\(0\)的整數。\(\varphi(1)=1\)(唯一和\(1\)互質的數(小於等 於1)就是1本身)。 (注意:每種質因數只一個。比如\(12=2*2*3\)
    那麼\(φ(12)=12*(1-1/2)*(1-1/3)=4\)

推論:

  • \(n\)為奇數時,有\(\varphi(2n)=\varphi(n)。\)

  • 因為\(2\)和奇數互質,所以\(\varphi(2)*\varphi(n)=\varphi(2n)\),又因為\(\varphi(2)=1\),所以\(\varphi(n)=\varphi(2n)\)

  • \(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)\), 證明與上述類似。

演算法實現

  1. 用通式直接求:
int Euler(int n)   //1.直接求尤拉函式的值
{
    int rea=n;
    for(int i=2; i*i<=n; i++)
        if(n%i==0)//第一次找到的必為素因子
        {
            rea=rea-rea/i;
           while(n%i==0){
                n=n/i;//把該素因子全部約掉
            }
        }
    if(n>1)
        rea=rea-rea/n;
    return rea;
}
  1. 素數表實現

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++)
        {
           // cout<<i*p[j]<<endl;
            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/p[i];
 
            while(n%p[i]==0){
                n=n/p[i];
            }
        }
    if(n>1)
        rea=rea-rea/n;
    return rea;
}
  1. 遞推求尤拉函式
int pp[20000];
for(int i=1; i<=maxn; i++)
    pp[i]=i;
for(int i=2; i<=maxn; i+=2)
    pp[i]/=2;
for(int i=3; i<=maxn; i+=2)
    if(pp[i]==i)
        for(int j=i; j<=maxn; j+=i)
            pp[j]=pp[j]/i*(i-1);