擴展歐幾里得算法(含嚴謹證實)

要整擴展歐幾里得,咱們確定要學會歐幾里得算法,若是你沒有學過gcd(a,b)=gcd(b,a%b),那麼打開這個連接:歐幾里得算法html

好了,若是你已經學完了歐幾里得,那麼就能默認你知道gcd(a,b)=gcd(b,a%b),那麼什麼是擴展歐幾里得,就是對於ax+by=gcd(a,b),必定有一組整數解x,y(注意!不要用24和36這個例子卡我,x,y是整數,能夠爲負的!)ios

在證實以前,咱們須要明確一種術學上的證實工具,數學概括法:git

    最簡單和常見的數學概括法是證實當 n等於任意一個天然數時某命題成立。證實分下面兩步:

    證實當n= 1時命題成立。算法

    假設n=m時命題成立,那麼能夠推導出在n=m+1時命題也成立。(m表明任意天然數)工具

    而後命題得證。spa

    而在遞歸式中也是如此。可是會有所不一樣code

當b=0時,很明顯,這個定理時成立的,y取0,x取1,那麼等式成立htm

如今只須要證,假設定理gcd(b,a%b)成立,那麼定理在gcd(a,b)中也成立就行。blog

假設,b*x2+a%b*y2=gcd(b,a%b)時存在解x2,y2遞歸

那麼,須要證實,a*x1+b*y1=gcd(a,b)存在解x1,y1,

咱們令a=k*b+c,也就是c是a%b.

移項得:c=a-k*b.將這個式子代入到須要證實的式子:b*x2+(a-k*b)*y2=gcd(b,a%b),再將其運用乘法分配律:b*x2+a*y2-k*b*y2=gcd(b,a%b)

再合併同類項:a*y2+b*(x2-k*y2)=gcd(b,a%b)=gcd(a,b)

咱們只須要讓x=y2,y=(x2-k*y2)不就好了?

得證,而後代碼實現過程也是怎麼寫的。

(已知a、b,求一組解x、y使ax+by=gcd(a,b))

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define REP(i,k,n)  for(int i=k;i<=n;i++)
#define in(a) a=read()
using namespace std;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar())
        if(ch=='-')
            f=-1;
    for(;isdigit(ch);ch=getchar())
        x=x*10+ch-'0';
    return x*f;
}
int x,y,t,A,B,d;
inline void exgcd(int a,int b,int &x,int &y,int &d){
    if(!b)  d=a,x=1,y=0;
    else  exgcd(b,a%b,x,y,d),t=x,x=y,y=t-a/b*y;
}
int main(){
    in(A),in(B);
    exgcd(A,B,x,y,d);
    cout<<d<<" "<<x<<" "<<y;
}
    

 最後,再說一下怎麼經過擴展歐幾里得解不定方程ax+by=c.(x、y爲整數)

首先,咱們必須保證,c能整除gcd(a,b)要否則就無解

而後咱們找特解:講a,b除以gcd(a,b),獲得a0,b0使他們互質,再用擴展歐幾里得求a0*x+b0*y=1的解x0,y0(這組解是特解)

而後通解就是x=x0+b0*t,y=y0+a0*t。

相關文章
相關標籤/搜索