1. 程式人生 > >擴展歐幾裏得(學習筆記)

擴展歐幾裏得(學習筆記)

證明 return 數學 應用 org 算法 inline 模板題 求解

貝祖定理:對於任意整數a,b,存在一對整數x,y,滿足\(ax+by=gcd(a,b)\).

以下證明中的[ ]是向下取整的意思(主要是我不會打向下取整的符號)

證明:數學歸納法.在歐幾裏得算法最後一步中,即b=0時,顯然有一對整數x=1,y=0,使得\(a*1+0*0=gcd(a,0)\);若b>0,則\(gcd(a,b)=gcd(b,a\mod b)\).假設存在一對整數x,y,滿足\(b*x+(a \mod b)*y=gcd(b,a \mod b)\),因為\(bx+(a \mod b)y=bx+(a-b[a/b])y\),繼續整理式子得\(ay+b(x-[a/b]y)\),所以令\(x'=y\)
\(y'=x-[a/b]y\),就得到了\(ax'+by'=gcd(a,b)\).因為x‘和y‘一定都是整數,所以定理是成立的.

根據上述定理和證明,有擴展歐幾裏得算法:

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

還有一種寫得更多的寫法,個人認為更好理解:

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

拓展:

對於更一般的方程\(ax+by=c\),它有解當且僅當\(gcd(a,b)|c\).

\(d=gcd(a,b)\),我們可以先用擴展歐幾裏得求出\(ax+by=d\)的一組特解\(x_0\)\(y_0\),然後令\(x_0\),\(y_0\)同時乘上\(c/d\),就得到方程\(ax+by=c\)的一組特解\((c/d)*x_0\),\((c/d)*y_0\),所以通解就是\((c/d)*x_0+k*(b/d)\),\((c/d)*y_0+k*(a/d)\),其中k是整數.

擴展歐幾裏得算法有一個常見的應用:求解線性同余方程.

給定整數a,b,m,求一個整數x滿足\(a*x ≡ b(\mod m)\),或者給出無解.因為未知數的指數為1,所以稱為一次同余方程,也稱線性同余方程.

\(a*x ≡ b(\mod m)\) 方程可以改寫為\(a*x+m*y=b\).這就回到了上面的拓展內容.

推薦一道模板題練練手,同余方程

擴展歐幾裏得(學習筆記)