【数论数学】扩展欧几里得算法

66 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第17天,点击查看活动详情

下面我们对扩展欧几里得算法进行简单的介绍。

问题定义

扩展欧几里得算法是欧几里得算法(又叫辗转相除法)的扩展。

已知整数 aa 和正整数 bb,扩展欧几里得算法可以在求得 aabb 的最大公约数的同时,找到满足贝祖等式

a×x+b×y=gcd(a,b)a\times x+b\times y=gcd(a,b)

的一组整数解 (x,y)(x,y)

思路

为求解

a×x+b×y=gcd(a,b)a\times x+b\times y=gcd(a,b)

根据普通欧几里得算法,我们知道

gcd(a,b)=gcd(b,amodb)gcd(a,b)=gcd(b,a\mod b)

假设我们已经求出了一组数 (x2,y2)(x_2,y_2),满足

b×x2+(amodb)×y2=gcd(b,amodb)b\times x_2+(a\mod b)\times y_2=gcd(b,a\mod b)

联立以上三个式子,我们可以得到

b×x2+(amodb)×y2=gcd(b,amodb)=gcd(a,b)=a×x+b×y\begin{aligned} b\times x_2+(a\mod b)\times y_2&=gcd(b,a\mod b)\\ &=gcd(a,b)\\&=a\times x+b\times y \end{aligned}

可推知

x1=y2y1=x2ab×y2\begin{aligned} x_1&=y_2\\ y_1&=x_2-\frac{a}{b}\times y_2 \end{aligned}

问题转化成了求解 x2x_2y2y_2

可以发现,表达式 a×x+b×y=gcd(a,b)a\times x+b\times y=gcd(a,b) 的形式与表达式 b×x2+(amodb)×y2=gcd(b,amodb)b\times x_2+(a\mod b)\times y_2=gcd(b,a\mod b) 完全相同,我们可以用求解第一个表达式的方式同理去求解第二个表达式。 不断重复以上过程,直到 yky_k 的系数为 00 时,我们可以得到最终表达式的的一组可行解(xk,yk)(x_k,y_k)

然后我们不断将求得的解带回上一层,最终可以求得贝祖等式

a×x+b×y=gcd(a,b)a\times x+b\times y=gcd(a,b)

的一组整数解 (x,y)(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;
}