浅谈 exgcd

众所周知欧几里得算法是:

\[\gcd(a,b)=\gcd(b,a\bmod b) \]

也叫辗转相除法。

拓展欧几里得算法(exgcd),可以用来找到形如 \(ax+by=\gcd(a,b)\) 的方程的一组特解

由裴蜀定理知,原方程一定有解。

我们利用辗转相除法(普通欧几里得算法)。

我们设 \(d=\gcd(a,b)\)

我们可以知道,我们辗转相除法的边界是 \(a=d,b=0\),此时我们可以知道 \(a\) 就是最大公约数,我们还可以知道,在这时一定有一解为 \(x=1,y=0\),即 \(1\times a+0\times b=d\)

我们知道 \(\gcd(a,b)=\gcd(b,a\bmod b)\),如果我们可以推导出每一次的解 \(x\)\(y\),与相除后的解 \(x'\)\(y'\) 的关系;我们就可以算出其中的一个解了,(\(x\)\(y\) 相当于是 \(a\)\(b\) 的解,\(x'\)\(y'\)\(a\) 变成了 \(b\)\(b\) 变成了 \(a\bmod b\) 时的解(辗转相除))。

轻易得知:

\(\begin{cases} ax+by=d\\ bx'+(a\bmod b)y'=d \end{cases}\)

则:

\[\begin{aligned} bx'+\left(a-b\left\lfloor\dfrac{a}{b}\right\rfloor\right)y'&=d\\ bx'+ay'-b\left\lfloor\dfrac{a}{b}\right\rfloor y'&=d\\ ay'+b(x'-\left\lfloor\dfrac{a}{b}\right\rfloor y')&=d\\ \text{解得:}&\begin{cases} x=y'\\y=x'-\left\lfloor\dfrac{a}{b}\right\rfloor y' \end{cases} \end{aligned} \]

然后我们知道 \(x\)\(x'\)\(y\)\(y'\), 的关系后就可以求解了:

#include<iostream>
#include<cstdio>
using namespace std;
void exgcd(int a,int b,int& x,int& y) //x.y也可以用pair返回,这里用了引用
{
	if (!b){x=1;y=0;return ;}     //边界
	gcd(b,a%b);                   //辗转相除
	int tmp=y;y=x-(a/b)*y;x=tmp;  //套公式
}
int main()
{
	int a,b,x,y;
	scanf("%d %d",&a,&b);
	exgcd(a,b,x,y);
	printf("%d %d",x,y);
	return 0;
}
posted @ 2020-05-08 23:59  Jijidawang  阅读(347)  评论(1编辑  收藏  举报
😅​