扩展欧几里得算法(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)}\) 就行了

写公式好累啊,啊啊啊,就当复习了

posted @ 2020-06-06 12:38  __int256  阅读(70)  评论(0编辑  收藏  举报