初等數論及其應用——歐拉函數


  歐拉函數這里理論性非常強,它與費馬小定理、剩余系、素數分解定理聯系,能夠推導出一系列的定理。

 

 

 

 

    計算phi(n)的編碼實現:

  

 #include<cstdlib>
#include<iostream>
using namespace std;

int phi(int n)
{
      int rea = n;
        for(int i = 2;i*i <=n;i++)

             if(n%i == 0)
             {
                 rea = rea - rea/i;
                 do
                    n /= i;
                 while(n%i == 0);
             }
             if(n > 1)
                  rea = rea - rea/n;
             return rea;

}

int main()
{
       int n;
       while(cin >> n && n)
       {
                  cout << phi(n) << endl;
       }
       return 0;
}


  計算區間[1,n]上歐拉函數值的和phi(2)+phi(3)+…+phi(n):

  當n取得較大整數時,如果用上文求單個整數的歐拉函數值然后相加,耗時太多,這里對於求區間歐拉函數值的和,有一個類似Eratosthenes篩法的優化。

  那么這里我們就像篩選素數那樣,得到一個素數然后設置第二層循環記錄這個素數整數倍的整數的“不完整歐拉值”,當該整數所有的素因子都遍歷到,歐拉值便更新到真實值。

 

#include <cstdio> //O(nloglogn)
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;

const int SIZE = 1000000 + 5;
int phi[SIZE];

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

}

int main()
{
    init();
    int n;

   while(scanf("%d",&n)!=EOF && n)
   {
              long long sum = 0;
        for(int i = 2; i <= n; i++)
        {
               sum += phi[i];
        }
        printf("%lld\n",sum);
   }

}


  應用1:既約真分數(poj 2478).

  給出整數n,讓你求解分母小於n的所有既約真分數的個數。

  分析:首先我們要搞懂什么是既約真分數,簡單來說,就是小於1的最簡分數。那么我們很容易將其與歐拉函數聯系起來,因為對於一個分母為n的既約真分數的個數,實際上就是phi(n),那么這個問題本質上就是求解phi(2)+...+phi(n).

 

  應用2:精簡打表數據.(uva 10820)

  有一道比賽題目,輸入兩個整數x、y(均小於等於n),輸出某個函數值f(x,y),一位選手想打表,但是如果全部打出來的話會造成內存超限,需要精簡。

  這道題目可以通過f(x,y)計算出f(kx,ky),k是任意正整數,這樣很多結果就不需要放在表中了。

  分析:通過“f(x,y)計算f(x,y)”這個題設條件,我們就能夠將其聯想到歐拉函數。最終表中存的二元組(x,y)只要互素,就能夠保證表中不存在任何“贅余(即可由表中的另外某組數據計算得來)”數據.

  假設x>y,那么我們枚舉x=2、3、…、n,二元組的數量應該是phi(2)+…+phi(n),由對稱性,最終結果應該乘2,而且不要忘記了(1,1)這個特殊情況。

  最終結果應該是2(phi(2)+…+phi(n)) + 1.

 

 

  應用3:公約數之和(uva 11426)

  給出整數n∈[2,4000000],求解∑gcd(i,j),其中(i,j)滿足1≤i<j≤n.

  分析:

 

 

  應用4:階乘的歐拉函數值(uva 11440)。

  給出整數n , m,n∈[2,10^7],n≥m≥1,n-m≤10^5.那么請問[2,N!]有多少個x滿足下列的性質,x的所有素因子都大於M.

  分析:

 

 

  參考代碼如下:

 

#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;

const int maxn = 10000000 + 5;
const int MOD = 100000007;

int vis[maxn] , phifac[maxn];

void gen_primes(int n) {
  int m = (int)sqrt(n+0.5);
  int c = 0;
  memset(vis, 0, sizeof(vis));
  for(int i = 2; i <= m; i++) if(!vis[i]){
    for(int j = i*i; j <= n; j+=i) vis[j] = 1;
  }
}

int main()
{
       int n , m;
       gen_primes(maxn);


       phifac[1] = phifac[2] = 1;
       for(int i = 3;i < maxn;i++)
             phifac[i] = ((long long)phifac[i-1] *(vis[i] ? i : i - 1)) %MOD;//題設給出取余運算MOD,中間過程一定要小心不要溢出。

       while(scanf("%d%d",&n , &m) && n)
       {
             int ans = phifac[m];

             for(int i = m + 1;i <= n;i++)  ans = (long long)ans*i%MOD;

             printf("%d\n",(ans - 1 + MOD)%MOD);

       }
       return 0;
} 

 


免責聲明!

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



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