1. 程式人生 > >『歐拉函數與線性篩』

『歐拉函數與線性篩』

true play forall 分解質 靈活運用 素數 復雜度 歐拉定理 也會

<更新提示>

<第一次更新>


<正文>

歐拉函數

定義

\(\forall\ a,b\in N\),若\(gcd(a,b)=1\),則稱\(a\)\(b\)互質。

對於一個正整數\(n\),我們將\(1-n\)中與\(n\)互質的數的個數稱為歐拉函數,記為\(\phi(n)\)

求解

若在算數基本定理中,有\(n=p_1^{a_1}*p_2^{a_2}*...*p_k^{a_k}\),則可以得到:
\[\phi(n)=n*\prod_{i=1}^{k}\frac{p_i-1}{p_i}\]

證明:
\(p\)\(n\)的一個質因子,則\(1-n\)\(p\)的倍數有\(p,2p,3p,...,\frac{n}{p}p\)

,即\(1-n\)中不含有因子\(p\)的數的個數為\(n-\frac{n}{p}\)個。
\(q\)\(n\)的另一個質因子,由容斥原理可得\(1-n\)中不含有因子\(p\)\(q\)的數的個數為\(n -\frac{n}{p}- \frac{n}{q}+ \frac{n}{pq}=n(\frac{p-1}{p})(\frac{q-1}{q})\)個。
推廣到\(n\)的每一個質因子,可得\(1-n\)中不與\(n\)含有任何共同質因子的數的個數為\(n*\prod_{i=1}^{k}\frac{p_i-1}{p_i}\)個,即\(\phi(n)=n*\prod_{i=1}^{k}\frac{p_i-1}{p_i}\)

利用如上公式,我們可以直接在分解質因數的過程中求得一個數的歐拉函數,時間復雜度為\(O(\sqrt n)\)

\(Code:\)

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

性質

\(1.\)對於質數\(p\),有\(\phi(p)=p-1\)

證明:由定義可得。

\(2.\)\(\forall \ n>1\)\(1-n\)中與\(n\)互質的數的和為\(\frac{n}{2}\phi (n)\)

證明:
由於\(gcd(n,x)=gcd(n,n-x)\),所以與\(n\)不互質的數\(n-x,x\)成對出現,且平均值為\(\frac{n}{2}\),因此與\(n\)互質的數的平均值也為\(\frac{n}{2}\)\(n\)互質的數的和即為\(\frac{n}{2}\phi (n)\)

\(3.\)\(gcd(a,b)=1\),則\(\phi(ab)=\phi(a)\phi(b)\)
\(4.\)歐拉函數是積性函數,即\(n=\prod p_i^{a_i}\)\(\phi(n)=\prod \phi(p_i^{a_i})\)
\(5.\)對於一個質數\(p\),若有\(p|n,p^2|n\),則\(\phi(n)=\phi(\frac{n}{p})*p\)
\(6.\)對於一個質數\(p\),若有\(p|n,p^2\not | n\),則\(\phi(n)=\phi(\frac{n}{p})*(p-1)\)

證明:
可以由歐拉函數的計算式直接推導得到。

\(7.\)\(\sum_{d|n}\phi(d)=n\)

證明:
設函數\(f(x)=\sum_{d|n}\phi(d)\),則\(f(nm)=\sum_{d|nm}\phi(d)\),若\(n,m\)互質,利用歐拉函數是積性函數可以得到:\[f(nm)=\sum_{d|nm}\phi(d)=\sum_{d_1|n}\sum_{d_2|m}\phi(d_1d_2)=\sum_{d|n}\phi(d)*\sum_{d|m}\phi(d)=f(n)f(m)\]
即函數\(f\)為積性函數。

對於一個質數\(p\)\[f(p^m)=\sum_{d|p^m}\phi(d)=\sum^{m}_{i=0}\phi(p^i)\],由等差數列求和可得\(f(p^m)=p^m\),即可得到\[f(n)=\prod_{i=1}^{m}f(p_i^{a_i})=\prod_{i=1}^{m}p_i^{a_i}=n\]

這些性質在不同的題目中有不同的作用,需要我們註意靈活運用。特別是性質\(6.\),在\(dirichlet\)卷積,\(M?bius\)反演中等內容中也會起到作用。

線性篩求解

對於求解\(1-n\)所有數的歐拉函數,如果直接使用分解質因數法,時間復雜度為\(O(n\sqrt n)\)

事實上,我們可以利用歐拉函數的性質\(1.\ 5.\ 6.\),再線性篩的求解過程中順帶地求解歐拉函數(線性篩見『素數 Prime判定和線性歐拉篩法 The sieve of Euler』)。

\(Code:\)

inline void eular(void)
{
    for (int i=2;i<=n;i++)
    {
        if (!flag[i])Prime[++cnt]=i,phi[i]=i-1;
        for (int j=1;j<=cnt&&i*Prime[j]<=n;j++)
        {
            flag[ 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);
        }
    }
}


<後記>
感謝\(hzk\) 歐拉函數的介紹(附加歐拉定理和費馬小定理的介紹)。

『歐拉函數與線性篩』