給定兩個正整數m和n,咱們計算它們的最大公因子d和兩個整數a和b,使得a*m+b*n=d算法
E1.置a'=b=1;a=b'=0;c=m,d=n;ide
E2.計算d和r,使得c=q*d+r;spa
E3.若r==0;則退出,當前已有a*m+b*n=d;code
E4;c=d;d=r;t=a';a'=a;a=t-q*a;t=b';b'=b;b=t-q*b;返回E2.blog
遞歸版本:遞歸
對於已有的m和n,假設m>n;若是刨除變量a,b,a',b';算法與歐幾里得算法徹底同樣,爲計算最大公約數的算法.數學
最終要求的爲a*m+b*n=d=GCD(m,n);若是改式子成立由歐幾里得算法可推出a'*n+b'*(m%n)=GCD(n,m%n);event
由於GCD(m,n)=GCD(n,m%n);class
因此a*m+b*n=a'*n+b'*(m%n)變量
=a'*n+b'*(m-(m/n)*n)
=a'*n+b'*m-b'*(m/n)*n
=b'*m+(a'-b'*(m/n))*n
因此a=b';b=a'-b'*(m/n);
能夠推出根據a‘、b'能夠計算a、b。
非遞歸版本:
設m爲r[0],n=r[-1];根據歐幾里得算法可推出
r[i-2]=r[i-1]*q[i]+r[i]; r=1...n+1; (1)
r[i](r=1...n+1)爲每次迭代的餘數,可知r[n+1]=0;且r[n]=GCD(m,n);
因爲每一個r都是前兩個r的組合,因此對於a*m+b*n=GCD(m,n)存在(可用數學概括法證實):
a[i]*m+b[i]*n=r[i]; (2)
當i==1時,根據(1)(2)式
a[1]*m+b[1]*n=r[1]
=r[-1]-r[0]*q[1]
=n-q[1]*m
可推出:a[1]=-q[1],b[1]=1;
當i==2時,根據(1)(2)式
a[2]*m+b[2]*n=r[2]
=r[0]-r[1]*q[2]
=r[0]-(a[1]*m+b[1]*n)*q[2]
=m-a[1]*q[2]*m-b[1]*q[2]*n
=(1-a[1]*q[2])*m-b[1]*q[2]*n
可推出:a[2]=1-a[1]*q[2],b[2]=-b[1]*q[2];
當i>=3時,根據(1)(2)式
a[i]*m+b[i]*n=r[i]
=-q[i](a[i-1]*m+b[i-1]*n)+(a[i-2]*m+b[i-2]*n)
=(-q[i]*a[i-1]+a[i-2])*m+(-q[i]*b[i-1]+b[i-2])*n
對於i>=3,a[i]=-q[i]*a[i-1]+a[i-2],b[i]=-q[i]*b[i-1]+b[i-2];
當咱們定義:a[-1]=0,a[0]=1,b[-1]=1,b[0]=0時,可構造出a,b的公式
a[-1]=0,a[0]=1,a[i]=-q[i]*a[i-1]+a[i-2](i>=1)
b[-1]=1,b[0]=0,b[i]=-q[i]*b[i-1]+b[i-2](i>=1)
void EGCD(int m,int n) { int a,a1,b,b1,c,d,q,r,t; a1=b=1,a=b1=0,c=m,d=n; while(1) { q=c/d,r=c%d; if(r==0) { printf("(%d)*%d+(%d)*%d=%d\n",a,m,b,n,d); return; } c=d,d=r,t=a1,a1=a,a=t-q*a,t=b1,b1=b,b=t-q*b; } }