歐拉定理+歐拉篩選法


一、概念

互質關系

如果兩個整數(或者兩個以上的整數)的最大公約數是1,則稱他們為互質。也就是說兩個整數,除了1以外,沒有其它的最大公約數了,這兩個整數就叫做互質關系。
比如說7,11他們的最大公約數只有1,所以他們互質;8,10他們的最大公約數為1,2,所以這兩數不是互質關系。

歐拉函數

歐拉函數φ(n)是小於或等於n的正整數中與n互質的數的數目,稱為歐拉函數
比如說當n=8時,與8能形成互質關系的數有4個,分別是1,3,5,7,所以φ(8)=4
具體φ(n)函數的計算公式,可以分為以下四種情況:

情況一: 當n=1,φ(1)=1

因為1與任何整數都是互質關系,所以當n=1時,φ(1)=1

情況二:當n為質數,φ(n)=n-1

因為質數與小於它的每一個數,都構成互質關系,所以當n為質數時,φ(n)=n-1 。
比如說n=3時,1,2都跟他是互質關系, n=7時,1,2,3,4,5,6都跟他是互質關系。

情況三:n = p^k (p為質數,k為指數,且大於等於1),n是質數的k次方,則φ(p^k) = p^k - p^(k-1) = p^k(1 - 1/p)

比如:φ(8) = φ(2^3) = 2^3 - 2^2 = 4
φ(27) = φ(3^3) = 3^3(1 - 1/3) = 18

情況四: n是兩個互質的整數之積,如:n = p1 * p1,則 φ(n) = φ(p1p2) = φ(p1)φ(p2)

比如:φ(56)=φ(8×7)=φ(8)×φ(7)=4×6=24

二、定理

同余定理

給定一個正整數n,如果兩個整數a和b滿足a-b能夠被n整除,即(a-b)/n得到一個整數,那么就稱整數a與b對n同余,記作a≡b(mod n)。這就是同余定理
例如:26≡2(mod 12), 26%12 余2, 2%12余2, 26-2/12 = 0,所以26與2對模12同余

 

歐拉定理

在數論中,歐拉定理是一個關於同余的性質。歐拉定理表明,若n,a為正整數,且n,a互素(即\gcd(a,n)=1),則

a^{\varphi(n)} \equiv 1 \pmod n



a^{\varphi(n)}與1在模n下同余;\varphi(n)為歐拉函數。

首先看一個基本的例子。令a = 3,n = 5,這兩個數是互素的。比5小的正整數中與5互素的數有1、2、3和4,所以\varphi(5)=4。計算:a^{\varphi(n)} = 3^4 = 81,而81 \equiv 80 + 1 \equiv 1 \pmod{5}。與定理結果相符。

這個定理可以用來簡化冪的模運算。比如計算7^{222}的個位數,實際是求7^{222}被10除的余數。7和10互素,且\varphi(10)=4。由歐拉定理知7^4\equiv 1\pmod {10}。所以  7^{222}= 7^{4\cdot 55+2}= (7^4)^{55}\cdot 7^2\equiv 1^{55}\cdot 7^2\equiv 49\equiv 9\pmod{10}      //歐拉函數φ(n)的作用就是把ap表示成aφ(n)*x+y
一般地,在簡化冪的模運算的時候,(當a和n互素) 我們要對a的指數取模\varphi(n)

x\equiv y \pmod {\varphi(n)},則a^x \equiv a^y \pmod n

 

三、求歐拉函數\varphi(n)

一、直接法

原理:

Euler函數表達通式:euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn),其中p1,p2……pn為x的所有素因數,x是不為0的整數。euler(1)=1(唯一和1互質的數就是1本身)。

//直接法
int euler(int n)
{
  int res=n,a=n;
  for(int i=2;i*i<=a;i++)
  {
    if(a%i==0)
    {
      res=res/i*(i-1);
      while(a%i==0)
        a=a/i;
    }
  }
  if(a>1)
    res=res/a*(a-1);
    return res;
  }
 

二、歐拉篩選法

i表示當前做到的這個數,prime[j]表示當前做到的質數,那要被篩掉的合數就是i*prime[j]。若prime[j]在這個合數里只出現一次(i%prime[j]!=0),也就是i和prime[j]互質時,則根據歐拉函數的積性函數的性質,phi[i * prime[j]]=phi[i] * phi[prime[j]]。若prime[j]在這個合數里出現了不止一次(i%prime[j]=0),也就是這個合數的所有質因子都在i里出現過,
那么根據公式,φ(i * prime[j])=φ(i) *prime[j]。復雜度為O(n)。其中得到的prime[n]是1~n的所有質數
void euler(int n)
{
    phi[1]=1;//1要特判 
    for (int i=2;i<=n;i++)
    {
        if (flag[i]==0)//這代表i是質數 
        {
            prime[++num]=i;
            phi[i]=i-1;
        }
        for (int j=1;j<=num&&prime[j]*i<=n;j++)//經典的歐拉篩寫法 
        {
            flag[i*prime[j]]=1;//先把這個合數標記掉 
            if (i%prime[j]==0)
            {
                phi[i*prime[j]]=phi[i]*prime[j];//若prime[j]是i的質因子,則根據計算公式,i已經包括i*prime[j]的所有質因子 
                break;//經典歐拉篩的核心語句,這樣能保證每個數只會被自己最小的因子篩掉一次 
            }
            else phi[i*prime[j]]=phi[i]*phi[prime[j]];//利用了歐拉函數是個積性函數的性質 
        }
    }
}

 

三、另一種更簡潔的篩選法、推薦

const int maxn = 1e6+10;
int prim[maxn], w[maxn], cnt = 0;//prim[i]起標記作用,prim[i]==0表示i是質數,注意這里把1也標記成了質數
int x[maxn];//x[i]表示偶數是i的符合條件的兩個質數是x[i]和i-x[i];
void init()
{
  memset(prim, false, sizeof(prim));
  prim[1]=1;//1不是素數
  for(int i = 2; i < maxn; i++)
  {
    if(prim[i]) //判斷i是否為偶數
      continue;
    w[cnt++] = i;//w存質數
    for(int j = i << 1; j < maxn; j+=i)//把所有質數的倍數標記
     prim[j] = true;
  }
  
}

 

 

 歐拉公式的延伸:小於n的且與n互質的數的和是euler(n)*n/2

 


來源:CSDN
原文:https://blog.csdn.net/u012861385/article/details/24271435

鏈接: https://www.jianshu.com/p/9007f61e27a8
來源:簡書

 


免責聲明!

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



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