扩展欧几里得算法(exgcd)
前言
1
\(gcd(a,b)=gcd(b,a\%b),(gcd(a,0)=a)\)
小证一下吧
设 \(d=gcd(a,b)\) 则 \(a=d*k,b=d*k'\)
当\(a\%b!=0\),则 \(a\%b=a-\left\lfloor \dfrac ab \right\rfloor * b = (k-\left\lfloor \dfrac ab \right\rfloor*k')d\) 并没有损失掉 \(d\)
当 \(a\%b=0\) 时,\(b=gcd(a,b)\)
2
\(a*x+b*y=c\) 有解当且仅当 \(gcd(a,b)|c\)
这个就不多说了
exgcd
扩展欧几里得算法,求解出一组解 \(x,y\) 使得 \(a*x+b*y=gcd(a,b)\)
我们当前有 \(gcd(a,b)=gcd(b,a\%b),a\%b=a-\left\lfloor \dfrac ab \right\rfloor * b\)
用 \(b\) 代替 \(a\) , 用 \(a\%b=a-\left\lfloor \dfrac ab \right\rfloor * b\) 代替 \(b\) 则原式成为
\(b*x'+(a-\left\lfloor \dfrac ab \right\rfloor * b)*y'=gcd(a,b)\) 注意 \(x' \ne x,y' \ne y\)
我们大力化式子,差开 \((a-\left\lfloor \dfrac ab \right\rfloor * b)*y\)
原式变为
\(b*x'+a*y'-b*\left\lfloor \dfrac ab \right\rfloor*y'=gcd(a,b)\)
把 \(a\) 和 \(b\) 放到一起
\(a*y'+b*(x'-\left\lfloor \dfrac ab \right\rfloor*y')=gcd(a,b)\)
因此我们得出 , \(x=y',y=x'-\left\lfloor \dfrac ab \right\rfloor*y'\)
当我们求出 \(gcd(a,b)\) 时 \(b=0\) 此时 \(a*x+b*y=a\) 我们让 \(x=1,y=0\) 即可
这样反向推回去就行了
放下代码吧
int exgcd(int a,int b,int &x,int &y){
if(!b){ x=1,y=0; return a; }
int gcd=exgcd(b,a%b,y,x);
y-=a/b*x;
return gcd;
}
最后我们求得了 \(a*x+b*y=gcd(a,b)\) 如何求 \(a*x+b*y=c\) 呢?
让 \(x,y\) 分别乘上 \(\dfrac c{gcd(a,b)}\) 就行了
现在我们已经求出了一组解 \(x,y\)如何得到另一组解 \(x',y'\) 呢?
只需要让 \(x'=x+\dfrac{b}{gcd(a,b)},y'=y-\dfrac{a}{gcd(a,b)}\) 即可
证明
将 \(x',y'\) 带入 \(a*x+b*y=gcd(a,b)\) 中 发现多出来的项消掉了
简单推导可知,这是 \(x,y\) 所能变动的最小范围
那么,我们知道了这个,就可以求出 \(x\) 的最小整数解,只需要让 \(x\%\dfrac b{gcd(a,b)}\) 就行了
写公式好累啊,啊啊啊,就当复习了