偶然看到大神Katoumegumi的欧几里得推导过程,感觉非常接地气。借此收藏。
对于一个方程a∗x+b∗y=gcd(a,b)
来说,我们可以做如下的推导:
设有a∗x1+b∗y1=gcd(a,b)
;
同时我们有b∗x2+(a%b)∗y2=gcd(b,a%b)
;
对于这个方程组,我们希望知道的是x1,x2,y1,y2
之间的关系,这样我们才可以递归解决这个问题
我们观察b∗x2+(a%b)∗y2
这个式子,我们可以将(a%b)
写作(a−⌊ab⌋∗b)
,将括号打开常数a,b
合并,合并之后的结果为a∗y2+b∗(x2−⌊ab⌋∗y2))
由于欧几里得算法的原理gcd(a,b)==gcd(b,a%b)
,我们将两式子联立,对比系数即可得到x1=y2,y1=x2−⌊ab⌋∗y2
这个递归的边界是什么呢?我们知道,当朴素欧几里得到达边界时,return gcd(a,0)=a
,那么边界条件就是对a∗x0+b∗y0=a
求解,很显然,此时x0=1,y0=0
当我们递归求出了一个方程的特解时,如何求出这个方程的通解呢?
方程a∗x+b∗y=gcd(a,b)
中,如果将x加上一个常数k1,y
减去一个常数k2
,仍然保持原方程成立,那么x+k1,y−k2
就是方程的一个新解,这个k应该如何选择呢?
实际上很简单,a∗(x+k1)+b∗(y+k2)=gcd(a,b)
,打开括号,a∗x+a∗k1+b∗y−b∗k2=gcd(a,b)
;
我们保证原方程成立,就需要a∗k1==b∗k2
,那么显然k1=b,k2=a
是一种合理的情况,但是这样是无法包含所有整数解的,因为我们加上的这个值并非是最小值
那我们应该加上什么值才行呢?我们发现当a∗k1==b∗k2=t∗lcm(a,b)
可以保证得到所有解,于是每次寻找解就可以分别在x
加上bgcd(a,b),在y减去agcd(a,b)
就可以了
对于方程a∗x+b∗y=c
我们又该如何求解?我们发现如果(c%gcd(a,b)!=0)
那么这个方程是无解的,而如果gcd(a,b)∗t==c
,我们就可以按上面的方法求解之后对我们的解乘上一个t(t=cgcd(a,b))
int exgcd(int a,int b,int &x1,int &y1)
{
if(!b)
{
x1=1,y1=0;
return a;
}
int x2,y2;
int d=exgcd(b,a%b,x2,y2);
x1=y2,y1=x2-(a/b)*y2;
return d;
}
code:https://www.cnblogs.com/KatouKatou/p/9818175.html