歐拉函數


  歐拉函數,它又稱為Euler's totient function、φ函數、歐拉商數等,對正整數n,歐拉函數是小於n且和n互質的正整數(包括1)的個數。例如Euler(8)=4,因為1,3,5,7均和8互質,下面用E(n)表示歐拉函數的值。

  Euler函數表達通式:E(x)=x*(1-1/p1)*(1-1/p2)*(1-1/p3)*(1-1/p4)…(1-1/pn),其中p1,p2……pn為x的所有素因數,x是不為0的整數。E(1)=1(唯一和1互質的數就是1本身)。
  歐拉公式的延伸:一個數的所有質因子之和是 E(n)*n/2。
  歐拉定理:對於互質的正整數a和n,有a^E(n) ≡ 1 mod n。
  歐拉函數是積性函數——若m,n互質,E(m*n)=E(m)*E(n)。
  若n是質數p的k次冪,E(n)=p^k-p^(k-1)=(p-1)*p^(k-1),因為除了p的倍數外,其他數都跟n互質。
  特殊性質:當n為奇數時,E(2n)=E(n)

先是直接根據公式求歐拉函數的值:

//euler(x) = x*(1 - 1/p1)*(1 - 1/p2)*(1 - 1/p3)...(1 - 1/pn)   p1 p2..是x的所有的質因子且各不相同  x != 0
//**質因子之和是euler(x)*x / 2
#include <iostream>

using namespace std;

int Euler(int n)
{
    int res = n , a = n;
    for(int i = 2 ; i*i <= a ; i++)
    {
        if(a % i == 0)  //i一定是素數
        {
            res = res / i * (i - 1);  //根據公式
            while(a % i == 0)  //把相同的除數排除
            {
                a /= i;
            }
        }
    }
    if(a > 1)  //最后只剩下 小於4的素數  或者n本身就是素數
        res = res / a *(a - 1);
    return res;
}

int main()
{
    int n;
    while(cin >> n)
    {
        cout << Euler(n) << endl;
    }
}

顯然當n比較大的時候用打表訪問比較快,下面是篩選法打歐拉函數表 

//離線打表
//篩選法求歐拉函數,時間復雜度O(nloglogn)
//跟埃式篩法求素數差不多
#include <iostream>

using namespace std;

const int MAXN = 100010;
int a[MAXN];

void init()
{
    for(int i = 1 ; i <= MAXN ; i++)
        a[i] = i;
    a[1] = 0;
    for(int i = 1 ; i <= MAXN ; i++)
    {
        if(a[i] == i)
        {
            for(int j = i ; j <= MAXN ; j += i)
                a[j] = a[j] / i * (i - 1);
        }
    }
}

int main()
{
    init();
    int n;
    while(cin >> n)
    {
        cout << a[n] << endl;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM