1. 程式人生 > >【演算法】歐幾里得——GCD引發的討論

【演算法】歐幾里得——GCD引發的討論

歐幾里得演算法

任務

求兩個數a,b的最大公約數gcd(a,b)

說明

由貝祖定理[若設a,b是整數,則存在整數x,y,使得ax+by=gcd(a,b)]得,gcd(a,b)=(b,a-b),其中a≥b。通過這樣不斷的迭代,知道b=0,就是原來數對的最大公約數。考慮到只使用減法會超時,我們觀察到如果a-b仍然大於b的話,要進行一次同樣的操作,就把a減到不足b為止,所以有gcd(a,b)=gcd(b,a mod b)。由此可以在log的時間內求出兩個數的gcd。

程式

int gcd(int a,int b);

複雜度

O(logN),其中N和a,b同階

輸入

a,b兩個整數

輸出

a,b的最大公約數

程式碼

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

擴充套件歐幾里得

任務

求出A,B的最大公約數,且求出X,Y滿足AX+BY=GCD(A,B)。

說明

要求X,Y,滿足:AX+BY=GCD(A,B)。
當B=0時,有X=1,Y=0時等式成立。
當B>0時,在歐幾里得演算法的基礎上,已知:
GCD(A,B)=GCD(B,A mod B)
先遞迴楸樹X’,Y’滿足:
BX’+(A mod B)Y’ = GCD(B,A mod B) = GCD(A,B)
然後可以回推,我們將上式化簡得:
BX’+(A-A/B*B)Y’=GCD(A,B)
AY’+BX’-(A/B)*BY’=GCD(A,B)
這裡除法指整除。把含B的因式提取一個B,可得:
AY’+B(X’-A/B*Y’)=GCD(A,B)
故X=Y’,Y=X’-A/B&Y’

程式

int extend_gcd(int a,int b,int &x,int &y);

複雜度

O(logN),其中N和a,b同階

輸入

a,b兩個整數
&x,&y引用,ax+by=GCD(a,b)的一組解

輸出

a,b的最大公約數
呼叫後x,y滿足方程ax+by=GCD(a,b)。

程式碼

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

參考文章:
ACM國際大學生程式設計競賽:演算法與實現
百度百科