1. 程式人生 > >擴充套件歐幾里得演算法(exgcd) 學習筆記

擴充套件歐幾里得演算法(exgcd) 學習筆記

定義

首先引入一個叫做貝祖定理的東西

對於a,bN,x,yZ,使ax+by=(a,b)

已知a,b,求ax+by=(a,b)一組可行解的演算法即為擴充套件歐幾里得演算法。

演算法流程

首先我們知道用來求最大公因數的歐幾里得演算法。

int gcd(int a,int b)
{
    if (!b) return a;
    else return gcd(b,a/b)
}

擴充套件歐幾里得其實是在歐幾里得演算法的基礎上執行的,時間複雜度也在log級別。
假設現在ax+by=(a,b),那麼(b,a%b)=(a,b),所以bx+(a%b)y=(a,b)
又因為a

%b=a(a/b)b,所以
(a,b)=bx+(a(a/b)b)y=bx+ay(a/b)by=ay+b(x(a/b)y)
由此可以知道下一組滿足條件的解為x=y,y=x(a/b)y
當b=0時,即a為最大公因數。這時只需要保證a的係數即x=1即可,y取任意值都不影響,不妨設y=0。
這就是整個擴充套件歐幾里得演算法的過程。

int exgcd(int a,int b,int &x,int &y)
{
    if (!b)
    {
        x=1,y=0;
        return a;
    }
    int ans=exgcd(b,a%b
,x,y); int t=x; x=y; y=t-(a/b)*y; return ans; }

其實擴充套件歐幾里得還有更簡單的寫法(from fye)

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

實際問題

實際上,在用exgcd解決問題的時候還有一些問題。

一般型等式

比如要求ax+by=c的值,首先可以將等式兩遍同時除以(a,b),如果不能整除則無解,因為c無論如何不為ab的倍數。
那麼現在等式變成了a

x+by=c(a,b)=1,為了滿足擴歐的條件使ax+by=(a,b)=1,可以將等式兩遍同時除以c,得到axc+byc=1。這樣就可以直接利用exgcd求出xcyc的值,然後再乘回去就可以了。
還有就是,用exgcd求出來的想x,y滿足這樣的性質{|x|+|y|}min,證明戳這裡
求出來可行解了之後再將x不斷-b/(a,b),y不斷+a/(a,b),解仍然成立。

逆元

ax1(modp),(a,p)=1,則x為a的逆元。
將等式化簡即可得到axpy=1,即為exgcd的經典模型。