1. 程式人生 > >歐幾里得與擴充套件歐幾里得

歐幾里得與擴充套件歐幾里得

歐幾里得:

int gcd(int a, int b)
{
    return !b ? a : gcd(b, a%b);
}
int lcm(int a, int b)//最小公倍數
{
    return a / gcd(a, b) * b;//先除後乘避免溢位
}

擴充套件歐幾里得:

存在整數對(x,y)使得ax+by=gcd(a,b)
推導過程:
用遞迴求解擴充套件歐幾里得,設已經求出了下一層遞迴的解,即:ax1+by1=gcd(a,b)(x1,y1)
a%b=a(a/b)b
(x1,y1)代入到bx1+(a%b)y1=gcd(a,b)中,得
bx1+(a

(a/b)b)y1=gcd(a,b)=>ay1+b(x1(a/b)y1)=gcd(a,b)
b=0時,顯然有a1+b0=gcd(a,b)
寫成程式碼,模板如下

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

求解不定方程:

c%gcd(a,b

)=0,則存在整數對(x,y),使得ax+by=c
通過上面的方法可得到一組特解(x0,y0)使得ax+by=gcd(a,b),那麼如何在無窮多個解中求出xy最小正整數解。

證明:

首先 ax0+akb/gcd(a,b)+by0akb/gcd(a,b)=gcd(a,b)
a(x0+kb/gcd(a,b))+b(y0ka/gcd(a,b))=gcd(a,b)
通解為x=x0+kb/gcd(a,b)y=y0ka/gcd(a,b),其中k=...2,1,0,1,2...
在所有解中最小的正整數為(x0+b/gcd(a,b))
所以對於方程ax+by=c,最小正整數解(以x

為例)為(x0c/gcd(a,b)+b/gcd(a,b))
注意:若b為負數,需將b轉換為正數。

int cal(int a, int b, int c)
{
    int x, y;
    int gcd = extgcd(a, b, x, y);
    if(c % gcd != 0) return -1;
    x *= c/gcd;
    b /= gcd;
    if(b < 0) b = -b;
    int ans = x % b;
    if(ans <= 0) ans += b;
    return ans;
}

同餘方程:

根據上面的內容,我們可以得到:

axb(modn)