给定两个正整数m和n,我们计算它们的最大公因子d和两个整数a和b,使得a*m+b*n=d
算法流程
E1.置a'=b=1;a=b'=0;c=m,d=n;
E2.计算d和r,使得c=q*d+r;
E3.若r==0;则退出,当前已有a*m+b*n=d;
E4;c=d;d=r;t=a';a'=a;a=t-q*a;t=b';b'=b;b=t-q*b;返回E2.
证明
递归版本:
对于已有的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);
因为GCD(m,n)=GCD(n,m%n);
所以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; } }