欧几里得算法提供了一种快速计算最大公约数的方法。而扩展欧几里得算法不仅能够求出其最大公约数。而且能够求出m,n和其最大公约数构成的不定方程mx+ny=d的两个整数x,y(这里x和y不一定为正数)。
在欧几里得算法中,终止状态是n == 0时,这时候其实就是gcd(m,0);我们想从这个最终状态反推出刚开始的状态。由欧几里得算法可知。
g
c
d
(
m
,
n
)
=
g
c
d
(
n
,
m
m
o
d
n
)
gcd(m,n) = gcd(n,m \ mod \ n)
gcd(m,n)=gcd(n,m mod n)
那么有如下表达式:
g c d ( m , n ) = m × x 1 + n × y 1 gcd(m,n) = m \times x1+n \times y1 gcd(m,n)=m×x1+n×y1
g c d ( n , m m o d n ) = n ∗ x 2 + ( m − m / n ∗ n ) ∗ y 2 gcd(n,m mod n) = n*x2+(m - m/n*n)*y2 gcd(n,mmodn)=n∗x2+(m−m/n∗n)∗y2
(此处的m/n表示整除,例如:6/4 = 1;所以:m mod n = m % n = m - m / n * n)
化简上式有:nx2 + m * y2 - m/nn*y2
= my2 + n(x2 - m/n*y2)
与原式 gcd(m,n) = mx1+ny1;对比,容易得出:
x1 = y2
y1 = x2 - m/n*y2;
根据上面的递归式和欧几里得算法的终止条件n == 0,我们可以很容易知道最终状态是m * x1 + 0 * y1 = m;故:x1 = 1;根据上述的递推公式和最终状态,可以写出代码如下:
ll gcd(ll a,ll b,ll &x,ll &y){
if(!b){
x=1;y=0;
return a;
}
ll d=gcd(b,a%b,y,x);//注意这里x,y互相交换了一下
y-=a/b*x;//这里是在x,y互相交换的基础上对y=tmp-a/b*y的改进
return d;
}
通解
t
b
d
t\frac{b}{d}
tdb相当于
a
d
x
\frac{a}{d}x
dax