这个算法其实很早就接触过,只不过那个时候没有好好理解与消化,导致运用的不是很到位,有些地方用得不太好,现在写一篇博客来弥补一下,顺便复习与深入理解。。。。
首先exgcd主要是gcd即欧几里得算法的扩展,首先我们可以了解一下gcd:求最大公约数
1、欧几里得算法(gcd)
又名辗转相除法,是用来计算两个数的最大公约数,其中就是利用gcd(a,b)=gcd(b,a mod b)来求解。
下证gcd(a,b)=gcd(b,a mod b)的正确性:
设a,b的一个公约数为d
设a mod b=r,则a=kb+r(k为整数),r=a-kb
因为d|a, d|b
所以d|(a-kb)
理由如下:
即d|r,而r=a mod b
所以d为b,a mod b的公约数
又因为d也为a,b的公约数,所以gcd(a,b)=gcd(b,a mod b),所以最大公约数必然一样,得证。
int gcd(int a,int b)
{
if (b==0) return a;
return gcd(b,a%b);
}
2、扩展欧几里得(exgcd)
扩展欧几里得不仅能求出a,b的最大公约数,还能求出满足ax+by=gcd(a,b)的一组可行解。
求解过程中,扩展欧几里得比欧几里得多了一个赋值过程,具体证明如下:
设ax1+by1=gcd(a,b)
bx2+(a mod b)y2=gcd(b,a mod b)
因为由欧几里得算法可知,gcd(a,b)=gcd(b,a mod b)
所以ax1+by1=bx2+(a mod b)y2
因为
(注意:这里的
将右边移项,展开得:
ax1+by1=ay2+bx2-(a div b)*b*y2
所以可得:x1=y2
将得到的的x1,y1递归操作求解x2,y2,如此循环往复,将会像欧几里得一样得到b=0的情况,此时递归结束,返回x=1,y=0,回溯得解。
代码描述:
此函数返回的是a,b的最大公约数,同时也求解出满足ax+by=gcd(a,b)的一组可行的(x,y)
int Exgcd(int a,int b,int &x,int &y)
{
if (!b)
{
x=1;y=0;
return a;
}
int d=Exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-(a/b)*y;
return d;
}