开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第17天,点击查看活动详情
下面我们对扩展欧几里得算法进行简单的介绍。
问题定义
扩展欧几里得算法是欧几里得算法(又叫辗转相除法)的扩展。
已知整数 a 和正整数 b,扩展欧几里得算法可以在求得 a 与 b 的最大公约数的同时,找到满足贝祖等式
a×x+b×y=gcd(a,b)
的一组整数解 (x,y)。
思路
为求解
a×x+b×y=gcd(a,b)
根据普通欧几里得算法,我们知道
gcd(a,b)=gcd(b,amodb)
假设我们已经求出了一组数 (x2,y2),满足
b×x2+(amodb)×y2=gcd(b,amodb)
联立以上三个式子,我们可以得到
b×x2+(amodb)×y2=gcd(b,amodb)=gcd(a,b)=a×x+b×y
可推知
x1y1=y2=x2−ba×y2
问题转化成了求解 x2 和 y2。
可以发现,表达式 a×x+b×y=gcd(a,b) 的形式与表达式 b×x2+(amodb)×y2=gcd(b,amodb) 完全相同,我们可以用求解第一个表达式的方式同理去求解第二个表达式。
不断重复以上过程,直到 yk 的系数为 0 时,我们可以得到最终表达式的的一组可行解(xk,yk)。
然后我们不断将求得的解带回上一层,最终可以求得贝祖等式
a×x+b×y=gcd(a,b)
的一组整数解 (x,y)。
代码
#include <iostream>
using namespace std;
int exgcd(int a,int b,int &x,int &y)
{
if (b==0)
{
x=1,y=0;
return a;
}
int gcd=exgcd(b,a%b,x,y),t=x;
x=y,y=t-(a/b)*y;
return gcd;
}
int main()
{
int x,y,a,b;
cout<<"求解:ax+by=gcd(a,b)\na=";
cin>>a;
cout<<"b=";
cin>>b;
cout<<"gcd(a,b)="<<exgcd(a,b,x,y)<<endl;
cout<<"解得:x="<<x<<",y="<<y;
return 0;
}