本系列文章内容大多采集罗老师著作:《算法竞赛入门到进阶》 清华大学出版社, 感谢罗老师的支持。
从问题出发:
给出整数a、b、n,问方程: ax+by=n 什么时候有整数解?
有解的充分必要条件是 gcd(a,b)可以整除n。简单解释如下:
令 a = gcd(a,b)a′、b= gcd(a,b)b′,有 ax+by=gcd(a,b)****(a′x+b′y)=n;**如果x、y、a′ 、b′都是整数,那么b必须是 gcd(a,b)的倍数才有整数解 **。
例如 4x + 6y = 8、2x + 3y = 4 有整数解,4x + 6y=7则没有整数解。
如果确定有解,一种解题方法是先找到一个解(x₁+y₁),那么通解公式如下:
x = x₁ + bt
y = y₁ - at, t 是任意整数
所以,问题转化为如何求(x₁,y₁)。利用扩展欧几里得算法可以求出这个特解。
1. 扩展欧几里得算法
当方程符合 ax + by = gcd(a,b)时,可以用扩展欧几里得算法求(x₁,y₁)。程序如下:
void extend_gcd(int a, int b, int &x, int &y){//返回x,y,即一个特解(x₁,y₁)
if(b==0){
x=1, y=0;
return ;
}
extend_gcd(b,a%b, x, y);
int tmp = x;
x = y;
y = tmp - (a/b)*y
}
有时候为了化简描述,在ax + by=gcd(a,b)两边除以 gcd(a,b),得到 cx + dy=1,其中 c=a/gcd(c,b), d=b/gcd(a,b)。很明显,c、d是互质的。cx + dy=1的通解如下:
x = x₁ + dt;
y = y₁ - ct, t是任意整数
这里可以理解为二维坐标系中的直线上的点
2.求任意方程 ax + by =n 的一个整数解
用扩展欧几里得算法求解 ax + by = gcd(a,b)后,利用它进一步解任意方程 ax + by =n,得到一个整数解。其步骤如下:
(1)判断方程ax + by =n 是否有整数解,有解的条件是 gcd(a,b)可以整除n;
(2)用扩展欧几里得算法求 **ax + by =gcd(a,b)**的一个解(x₁,y₁);
(3)在 **ax₁ +by₁ =gcd(a,b)**两边同时乘以 n/gcd(a,b),得:
ax₁n/gcd(a,b) + by₁n/gcd(a,b) =n
(4)对照 ax + by= n,得到它的一个解(x₁′,y₁′)是:
x₁′=x₁n/gcd(a,b)
y₁′=y₁n/gcd(a,b)
3.应用场合
扩展欧几里得算法是一个很有用的工具,在竞赛中应用到一下场合:
(1)求解不定方程;
(2)求解模的逆元;
(3)求解同余方程。
虽然可以通过 ax + by = gcd(a,b) 得到通解,但是通常题目要求求特解。