众所周知欧几里得算法是:
[gcd(a,b)=gcd(b,amod \,b)
]
也叫辗转相除法。
拓展欧几里得算法(exgcd
),可以用来找到形如 (ax+by=gcd(a,b)) 的方程的一组特解。
由裴蜀定理知,原方程一定有解。
我们利用辗转相除法(普通欧几里得算法)。
我们设 (d=gcd(a,b))。
我们可以知道,我们辗转相除法的边界是 (a=d,b=0),此时我们可以知道 (a) 就是最大公约数,我们还可以知道,在这时一定有一解为 (x=1,y=0),即 (1 imes a+0 imes b=d)。
我们知道 (gcd(a,b)=gcd(b,amod b)),如果我们可以推导出每一次的解 (x) 和 (y),与相除后的解 (x') 和 (y') 的关系;我们就可以算出其中的一个解了,((x) 和 (y) 相当于是 (a) 和 $b (的解,)x'$ 和 (y') 是 (a) 变成了 (b),(b) 变成了 (amod b) 时的解(辗转相除))。
轻易得知:
(egin{cases} ax+by=d\ bx'+(amod b)y'=d end{cases})
则:
[egin{aligned}
bx'+left(a-bleftlfloordfrac{a}{b}
ight
floor
ight)y'&=d\
bx'+ay'-bleftlfloordfrac{a}{b}
ight
floor y'&=d\
ay'+b(x'-leftlfloordfrac{a}{b}
ight
floor y')&=d\
ext{解得:}&egin{cases}
x=y'\y=x'-leftlfloordfrac{a}{b}
ight
floor 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;
}