擴展歐幾里德算法

擴展歐幾里德算法

擴展歐幾里德算法是用來在已知a, b求解一組x,y,使它們滿足貝祖等式: ax+by = gcd(a, b) =d(解一定存在,根據數論中的相關定理)。擴展歐幾里德常用在求解模線性方程及方程組中。

基本介紹

  • 中文名:擴展歐幾里得算法
  • 外文名:extended Euclidean algorithm
  • 表達式:a*x+b*y=gcd(a,b)
  • 套用學科:數學,信息學
  • 適用領域範圍:數論,密碼學
歐幾里德算法,概述,公式表述,C++語言實現,pascal語言實現,擴展算法,c++語言實現,pascal語言實現,

歐幾里德算法

概述

歐幾里德算法又稱輾轉相除法,用於計算兩個整數a,b的最大公約數。其計算原理依賴於下面的定理:
gcd函式就是用來求(a,b)的最大公約數的。
gcd函式的基本性質:
gcd(a,b)=gcd(b,a)=gcd(-a,b)=gcd(|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++語言實現

int gcd(int a,int b){    return b?gcd(b,a%b):a;}

pascal語言實現

function gcd(a,b:longint):longint;begin    if b=0 then exit(a);    gcd:=gcd(b,a mod b);end;

擴展算法

對於不完全為 0 的非負整數 a,b,gcd(a,b)表示 a,b 的最大公約數,必然
存在整數對 x,y ,使得 gcd(a,b)=ax+by。

c++語言實現

int gcd(int a,int b,int &x,int &y){    if (b==0){        x=1,y=0;        return a;    }    int q=gcd(b,a%b,y,x);    y-=a/b*x;    return q;}

pascal語言實現

function gcd(a,b:longint; var x,y:longint):longint;var t:longint;begin    if b=0 then        begin            x:=1; y:=0;            exit(a);        end;    gcd:=gcd(b,a mod b,y,x);    y:=y-(a div b)*x;end;
求解 x,y的方法的理解
設 a>b。
1,顯然當 b=0,gcd(a,b)=a。此時 x=1,y=0;
2,a>b>0 時
設 ax1+ by1= gcd(a,b);
bx2+ (a mod b)y2= gcd(b,a mod b);
根據樸素的歐幾里德原理有 gcd(a,b) = gcd(b,a mod b);
則:ax1+ by1= bx2+ (a mod b)y2;
即:ax1+ by1= bx2+ (a - [a / b] * b)y2=ay2+ bx2- [a / b] * by2;
說明: a-[a/b]*b即為mod運算。[a/b]代表取小於a/b的最大整數。
也就是ax1+ by1 == ay2+ b(x2- [a / b] *y2);
根據恆等定理得:x1=y2; y1=x2- [a / b] *y2;
這樣我們就得到了求解 x1,y1 的方法:x1,y1 的值基於 x2,y2.
上面的思想是以遞歸定義的,因為 gcd 不斷的遞歸求解一定會有個時候 b=0,所以遞歸可以結束。
擴展歐幾里德算法
擴展歐幾里德算法是用來在已知a, b求解一組x,y使得ax+by = Gcd(a, b) =d(解一定存在,根據數論中的相關定理)。擴展歐幾里德常用在求解模線性方程及方程組中。下面是一個使用C++的實現:
int exGcd(int a,int b,int &x,int &y){    if(b==0)    {        x=1;y=0;        return a;    }    int r=exGcd(b,a%b,x,y);    int t=x;x=y;y=t-a/b*y;    return r;}
把這個實現和Gcd的遞歸實現相比,發現多了下面的x,y賦值過程,這就是擴展歐幾里德算法的精髓。
可以這樣思考:
對於a'=b,b'=a%b 而言,我們求得 x, y使得 a'x+b'y=Gcd(a',b')
由於b'=a%b=a-a/b*b (註:這裡的/是程式設計語言中的除法)
那么可以得到:
a'x+b'y=Gcd(a',b') ===>
bx+(a - a / b * b)y = Gcd(a', b') = Gcd(a, b) ===>
ay +b(x - a / b*y) = Gcd(a, b)
因此對於a和b而言,他們的相對應的p,q分別是 y和(x-a/b*y)
使用擴展歐幾里德算法解決不定方程的辦法
對於不定整數方程pa+qb=c,若 c mod Gcd(a, b)=0,則該方程存在整數解,否則不存在整數解。
有種較為不嚴謹的方法證明,不過至少彌補了一點空白,望某些數論大師補充修改:
由於我們知道,存在一組x與y使得a*x+b*y=gcd(a,b)。
將等式兩邊同時乘以整數k,即a*x*k+b*y*k=gcd(a,b)*k。如果c mod gcd(a,b)=f,則0<=f<gcd(a,b)。
那么可以令c=gcd(a,b)*k+f。這樣一來,就有a*x*k+b*y*k+f=c。
若f
0,由於f<gcd(a,b)<=a<=b(假設a<=b),所以不存在f=a*m(m為整數),也就不存在a*(x*k+m)+b*y*k=c。也就是說,不存在a*x+b*y=c的整數解x與y。
所以f=0,即只有當c mod gcd(a,b)=0時,a*x+b*y=c有正整數解。得證。
上面已經列出找一個整數解的方法,在找到p * a+q * b = Gcd(a, b)的一組解p0,q0後,p * a+q * b = Gcd(a, b)的其他整數解滿足:
p = p0 + b/Gcd(a, b) * t
q = q0 - a/Gcd(a, b) * t(其中t為任意整數)
至於pa+qb=c的整數解,只需將p * a+q * b = Gcd(a, b)的每個解乘上 c/Gcd(a, b) 即可,但是所得解並不是該方程的所有解,找其所有解的方法如下:
在找到p * a+q * b = Gcd(a, b)的一組解p0,q0後,可以
得到p * a+q * b = c的一組解p1 = p0*(c/Gcd(a,b)),q1 = q0*(c/Gcd(a,b)),p * a+q * b = c的其他整數解滿足:
p = p1 + b/Gcd(a, b) * t
q = q1 - a/Gcd(a, b) * t(其中t為任意整數)
p 、q就是p * a+q * b = c的所有整數解。
編程時 exgcd 更多用於求解“中國剩餘定理”相關知識 舉個例子比如n除以5餘2 除以13餘3 那么n最小是多少,所有的n滿足什麼條件?
n(min)=42
n=42+k*65
歐幾里德算法的擴展
擴展歐幾里德算法不但能計算(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 nk;    for(t3=x3%y3;t3!=0;t3=x3%y3)    {        k=x3/y3;        t2=x2-k*y2;t1=x1-k*y1;        x1=y1;x2=y2;x3=y3;        y1=t1;y2=t2;y3=t3;    }    if(y3==1)//有乘法逆元    {        ar=(y2+b)%b;//對求出來負的乘法逆元進行處理,使之在模b的完全剩餘集裡        br=(y1+a)%a;//原來這裡是錯的        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) = j t3(k) + r
則:
t3(k+1) = r
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) = r
= t3(k+1)
得證
因此,當最終t3疊代計算到1時,有t1× a + t2 × b = 1,顯然,t1是a模b的乘法逆元,t2是b模a的乘法逆元。

相關詞條

熱門詞條

聯絡我們