扩展欧几里德算法是用来在已知a, b求解一组整数解(x,y)使得ax+by=gcd(a,b),这个方程一定有解,记d=gcd(a,b),a=d*a',b=d*b',那么必须有d/b,否则方程变为a'x+b'y=b/d,左边是整数,右边却不是,这样就无解了。
C++实现:
int gcd(int a, int b, int &x, int &y)
{
if(b == 0)
{
x = 1;
y = 0;
return a;
}
int r = gcd(b, a % b, x, y);
int t = x;
x = y;
y = t - a / b * y;
return r;
}
把这个实现和欧几里得的递归实现相比,发现多了x,y赋值过程,
可以这样理解:
因为(a,b)和(b,a mod b)的公约数是一样的,对于a' = b,b' = a % b 而言,我们求得 x, y使得 a'x + b'y = gcd(a', b')
而b' = a % b = a - a / b * b,代入方程有:
a'x + b'y = gcd(a', b') ==>
bx + (a - a / b * b)y = gcd(a', b') = gcd(a, b) ==>
ay +b(x - a / b*y) = gcd(a, b)
这样a,b对应的x,y分别是y,x-a/b*y。
上面方程ax+by=gcd(a,b)只求出了一组解(x1,y1),如果c%gcd(a,b)==0,那么只要方程两边同时扩大c/gcd(a,b)倍即可,也就是说原方程a*x+b*y=c的一个特解是(x1*c/gcd(a,b), y1*c/gcd(a,b)),那么其他解呢?任取另外一组解(x2,y2),则ax1+by1=ax2+by2,变形得a(x1-x2)=b(y2-y1)。记gcd(a,b)=d,方程左右两边同时除以d,得
a'(x1-x2)=b'(y2-y1),其中a'=a/d,b'=b/d。而此时a'和b'互素,因此x1-x2一定是b'的整数倍,则y2-y1=ka'。
于是得出结论:若方程ax+by=c的一组整数解为(x0,y0),则它的任意整数解可以写成(x0+kb',y0-ka'),a'=a/gcd(a,b),b'=b/gcd(a,b),k 为任意整数。