1. 程式人生 > >推廣的歐幾里德演算法(求最大公約數和乘法逆元)

推廣的歐幾里德演算法(求最大公約數和乘法逆元)

歐幾里德演算法

歐幾里德演算法又稱輾轉相除法,用於計算兩個整數a,b的最大公約數。其計算原理依賴於下面的定理:

定理:gcd(a,b) = gcd(b,a mod b)

 證明:a可以表示成a = kb + r,則r = a mod b
 假設d是a,b的一個公約數,則有
 d|a, d|b,而r = a - kb,因此d|r
 因此d是(b,a mod b)的公約數
     
 假設d 是(b,a mod b)的公約數,則
 d | b , d |r ,但是a = kb +r 
 因此d也是(a,b)的公約數
     
 因此(a,b)和(b,a mod b)的公約數是一樣的,其最大公約數也必然相等,得證

歐幾里德演算法就是根據這個原理來做的,其演算法用C++語言描述為:

    void swap(int & a, int & b)
    {
        int c = a;
        a = b;
        b = c;
    }
    int gcd(int a,int b)
    {
        if(0 == a )
        {
            return b;
        }
        if( 0 == b)
        {
            return a;
        }
        if(a > b)
        {
            swap(a,b);
        }
        int c;
        for(c = a % b ; c > 0   c = a % b)
        {
            a = b;
            b = c;
        }
        return b;
    }

模P乘法逆元

對於整數a、p,如果存在整數b,滿足ab mod p =1,則說,b是a的模p乘法逆元。

定理:a存在模p的乘法逆元的充要條件是gcd(a,p) = 1

 證明:
 首先證明充分性
 如果gcd(a,p) = 1,根據尤拉定理,aφ(p) ≡ 1 mod p,因此
 顯然aφ(p)-1 mod p是a的模p乘法逆元。
     
 再證明必要性
 假設存在a模p的乘法逆元為b
 ab ≡ 1 mod p
 則ab = kp +1    ,所以1 = ab - kp
 因為gcd(a,p) = d 
 所以d | 1
 所以d只能為1

擴充套件歐幾里德演算法

擴充套件歐幾里德演算法不但能計算(a,b)的最大公約數,而且能計算a模b及b模a的乘法逆元,用C語言描述如下:

 int    gcd(int    a,    int    b    ,    int&    ar,int    &    br)
 {
  int    x1,x2,x3;
  int    y1,y2,y3;
  int    t1,t2,t3;
  if(0    ==    a)
  {//有一個數為0,就不存在乘法逆元
               ar    =    0;
               br    =    0    ;
               return    b;
  }
  if(0    ==    b)
  {
               ar    =    0;
               br    =    0    ;
               return    a;
  }
  x1    =    1;
  x2    =    0;
  x3    =    a;
  y1    =    0;
  y2    =    1;
  y3    =    b;
  int    k;
  for(    t3    =    x3    %    y3    ;    t3    !=    0    ;        t3    =    x3    %    y3)
  {
   k    =    x3    /    y3;
   t2    =    x2    -    k    *    y2;
   t1    =    x1    -    k    *    y1;
   x1    =    y1;
   x1    =    y2;
   x3    =    y3;
   y1    =    t1;
   y2    =    t2;
   y3    =    t3;
  }
  if(    y3    ==    1)
  {
   //有乘法逆元
   ar    =    y2;
   br    =    x1;
   return    1;
  }else{
          //公約數不為1,無乘法逆元
           ar    =    0;
           br    =    0;
           return    y3;
  }
 }

擴充套件歐幾里德演算法對於最大公約數的計算和普通歐幾里德演算法是一致的。說明為何可以計算乘法逆元,則比較難。

首先重複整除中的一個論斷:

如果gcd(a,b)=d,則存在m,n,使得d = ma + nb,稱呼這種關係為a、b組合整數d,m,n稱為組合係數。當d=1時,有 ma + nb = 1 ,此時可以看出m是a模b的乘法逆元,n是b模a的乘法逆元。

為了證明上面的結論,我們把上述計算中xi、yi看成ti的迭代初始值,考察一組數(t1,t2,t3),用歸納法證明:當通過擴充套件歐幾里德演算法計算後,每一行都滿足a×t1 + b×t2 = t3

 第一行:1 × a + 0 × b = a成立
 第二行:0 × a + 1 × b = b成立
 假設前k行都成立,考察第k+1行
 對於k-1行和k行有
 t1(k-1)    t2(k-1)  t3(k-1)
 t1(k)      t2(k)    t3(k)
 分別滿足:
 t1(k-1) × a + t2(k-1) × b = t3(k-1)
 t1(k)   × a + t2(k)   × b = t3(k)
 根據擴充套件歐幾里德演算法, 則:
  t3(k+1) = t3(k-1) - j × t3(k)
  t2(k+1) = t2(k-1) - j × t2(k)
  t1(k+1) = t1(k-1) - j × t1(k)
 則
         t1(k+1) × a + t2(k+1) × b 
        =t1(k-1) × a - j × t1(k) × a +
         t2(k-1) × b - j × t2(k) × b
       = t3(k-1) - j × t3(k)  
       = t3(k+1)
 得證

因此,當最終t3迭代計算到1時,有t1× a + t2 × b = 1,顯然,t1是a模b的乘法逆元,t2是b模a的乘法逆元。

參考C程式:

#include <stdio.h> #include <stdlib.h> #include <math.h>

//void euclid(long int,long int);

void main() {   long int i=119; //互素   long int j=67;   euclid(i,j); }

void euclid(long int a,long int b)  //假定a>b>0.求的是b模a的乘法逆元。 {   long int x1,x2,x3;   long int y1,y2,y3;   long int t1,t2,t3;   long int q;   x1=1;   x2=0;   x3=a;   y1=0;   y2=1;   y3=b;   while(1)   {      if(y3==0)      {           printf("The Max-public-gene is: %u\n",x3);          printf("no inverse.\n");          break;       }      if(y3==1)      {          printf("The Max-public-gene is: %u\n",y3);          while(y2<0) //此處while是否可以直接做一次if判斷?待以後在java上證明           {              y2=y2+a;            }          printf("The multi-inverse is: %u\n",y2);          break;       }      q=x3/y3;      t1=x1-q*y1;      t2=x2-q*y2;      t3=x3-q*y3;      x1=y1;      x2=y2;      x3=y3;      y1=t1;        y2=t2;      y3=t3;

}

}

原文地址:http://blog.163.com/[email protected]/blog/static/3350863020076205715383/  

相關推薦

推廣演算法大公約數乘法

歐幾里德演算法 歐幾里德演算法又稱輾轉相除法,用於計算兩個整數a,b的最大公約數。其計算原理依賴於下面的定理: 定理:gcd(a,b) = gcd(b,a mod b) 證明:a可以表示成a = kb + r,則r = a mod b 假設d是a,b的一個公約數,

擴充套件Extended Euclid演算法大公約數乘法

密碼學課本里面使用到的一個十分簡單的演算法,老師佈置的作業,就寫了一下...程式碼挺腦殘的,只要知道演算法的步驟,很好實現。 程式碼: #include<iostream> using namespace std; int a[3][3]; int coun

演算法大公因子及擴充套件乘法

一、歐幾里得演算法歐幾里得演算法又稱輾轉相除法,是指用於計算兩個正整數a,b的最大公約數。gcd(a,b)=gcd(b,a mod b)。演算法描述:1. 輸入:兩個非負整數a,b,且a≥b。2. 輸出

演算法兩個正整數的大公約數

  getchar()會接受前一個scanf的回車符 */ #include<stdio.h> void main() {     int temp;     int a,b;     s

算法--大公約數

clas pan nbsp 歐幾裏德 bsp sig while turn 最大 unsigned int Gcd(unsigned int M,unsigned int N) { unsigned int Rem; while(N > 0)

caioj 1153 擴充套件演算法解不定方程

模板題 注意exgcd函式要稍微記一下 #include<cstdio> #include<cctype> #include<algorithm> #define

擴充套件演算法乘法

eg:求5關於模14的乘法逆元 15 = 5*2+1 5 = 4*1+1 說明5與14互素,存在5關於14的乘法逆元 1 = 5-4 = 5-(14-5*2)= 5*3-14 因此5關於模14的乘法逆元為3  a存在模b的乘法逆元的充要條件是gcd(a,b)= 1 互質

演算法Euclidean algorithm

設兩數為a、b(a>b),用gcd(a,b)表示a,b的最大公約數,r=a (mod b) ,k=a/b(整除),即a÷b=k.......r。 1:令c=gcd(a,b),則設a=mc,b=nc // 因為c是最大公約數 2:根據a÷b=k.......r,可列k*b+r=a,代入a,b,解得

C語言輾轉相除法演算法大公約數

演算法敘述: 設(a,b)表示a和b的最大公約數 若c為a/b的餘數(c=a%b) 則(a,b)=(b,c). #include<stdio.h> int gcd(int a,int b

擴充套件演算法模版題+分析+題目HDU1576 A/B

首先給大家普及一下什麼是擴充套件歐幾里德演算法,它是由歐幾里德演算法演變的,即我們常說的輾轉相除法。 程式碼如下: int gcd(int a,int b){ return b?gcd(b,a%b):a; } 那麼對於不完全為0的非負整數,a,b,gcd(a,b

擴充套件演算法乘法C語言版

#include <stdio.h>   int ExtendedEuclid( int f,int d ,int *result);   int main()   {   int x,y,z;   z = 0;   printf("輸入

大公因子輾轉相除法原理擴充套件的演算法

while(n != 0) { r = m % n; m = n; n = r; } printf("Their greatest common divisor is %d.\n", m);

C語言輾轉相除/相減法演算法大公約數小公倍數

#include <stdio.h> #include <stdlib.h> //題目:輸入兩個正整數m和n,求其最大公約數和最小公倍數。 //採用任何兩種演算法來完成上述題目,並比較2種演算法的時間複雜度和空間複雜度。 int main() { int

同餘方程擴充套件演算法

同餘方程 時間限制: 1 Sec  記憶體限制: 128 MB 題目描述 求關於 x 的同餘方程 ax ≡ 1 (mod b)的最小正整數解。 輸入 輸入只有一行,包含兩個正整數 a, b,用一個空格隔開。 輸出 輸出只有一行,包含

演算法學習——演算法&擴充套件演算法

最大公約數/歐幾里德演算法(gcd) 歐幾里德演算法又稱輾轉相除法,證明可以度娘。 個人簡單腦部就是a和b兩個數的模還是a和b的最大公約數 int型別  int gcd(int a, int b) {return a%b==0?b:gcd(b,a%b);} long l

大公約數——演算法JAVA

歐幾里得演算法 問題描述:給出兩個數m,n,求解這兩個數的最大公因數 由於演算法比較簡單,這裡不再贅述,我做的這個演算法是默認了m>n,如果是對於任意兩個數來說的話,我們這裡還需要一個比較大小。

擴充套件的演算法乘法

計算乘法逆元,比如3mod8的乘法逆元為3 是如何用歐幾里得演算法計算的呢??? 數對 x,y ,使得 gcd(a,b)=ax+by。 c++語言實現: #include <iostream&

#數論# 演算法 、擴充套件演算法 、費馬小、求解ing

歐幾里德求gcd(輾轉相除法): 定理: gcd(a, b) = gcd(b, a % b) 兩個正整數a和b(a>b),它們的最大公約數等於a除以b的餘數c和b之間的最大公約數 證明: a可以表示成a = kb + r,則r = a %

演算法大公約數

歐幾里德演算法又稱輾轉相除法,用於計算兩個整數a,b的最大公約數。 定理:gcd(a,b) = gcd(b,a mod b)。 第一種可以寫成: int Gcd(int a, int b) { while(b != 0) { int r =

擴充套件演算法

新博文地址:  [狀態轉移思想解讀:歐幾里德演算法及擴充套件](http://blog.csdn.net/sunliymonkey/article/details/46755983) 歐幾里德是用來求最大公約數的,可以把它看成是狀態轉移, 對任意兩個數a,b(a>