数论入门_扩展欧几里得算法

EXGCD

学了扩展欧几里得算法好长时间了,打篇博客复习一下

具体推导与用法如下


拓展欧几里得算法

主要解决求解同余方程的问题

下面是一个关于x ,y的二元一次方程

  • ax + by = c

根据裴蜀定理 ,如果gcd(a,b) | c,则此方程存在整数解(充分必要条件)

因此我们仅当c=gcd(a,b)
所以 ax1 + by1 = gcd(a,b)

通过欧几里得算法,可得
gcd(a,b)=gcd(b,a%b)

这时 在 a=b,b=a%b的条件下
bx2 + a%b y2 = gcd(b,a%b)

所以 :

  • ax1 + by1 = bx2 + (a%b)y2

假设k=a/b(向下取整),r=a%b

那么 a = kb+r = b(a/b)+a%b,
a%b = r = a-kb = a-b(a/b)

bx2 + (a%b)y2

= bx2 + (a-b(a/b))y2

= bx2 - b(a/b)y2 + ay2

=b(x2 - (a/b)y2) + ay2

=ay2 + b(x2 - (a/b)y2)

所以可得:

bx2 + (a%b)y2 = ay2 + b(x2 - (a/b)y2)

ax1 + by1 = bx2 + (a%b)y2 = ay2 + b(x2 - (a/b)y2)

  • ax1 + by1 = ay2 + b(x2 - (a/b)y2)

惊喜地发现:

  • x1 = y2 , y1 = x2 - (a/b)y2

得到此递归转移公式后,开始打exgcd部分的代码

int exgcd(int a,int b,int &x1,int &y1) //附带求gcd的功能
{
	if(b==0){
		x=1;  //当 ax+by=gcd(a,b)中b=0时,a=gcd(a,b),x=1,y=0
		y=0;
		return a; //gcd功能实现,b=0时gcd(a,b)=a
	}
	int x2,y2;
	int t=exgcd(b,a%b,x2,y2);
	x1=y2;
	y1=x2-(a/b)*y2;
	return t;  //返回gcd(a,b)
}


特解求出了通解便也好求了

对于两个方程

ax1 + by1 = c1
, ax2 + by2 = c2

x1=(c1/c2)x2 , y1=(c1/c2)y2

所以此时回到在上面的方程

  • ax + by = c

x = x1 ( c / gcd(a,b))

y = y1 ( c / gcd(a,b))


完整代码

#include<iostream>
using namespace std;
int X,Y;
int x1,y1; 
int gcd(int a,int b)
{
	return b ?	gcd(b,a%b) : a;
}
int exgcd(int a,int b,int &x1,int &y1) //附带求gcd的功能
{
	if(b==0){
		x=1;  //当 ax+by=gcd(a,b)中b=0时,a=gcd(a,b),x=1,y=0
		y=0;
		return a; //gcd功能实现,b=0时gcd(a,b)=a
	}
	int x2,y2;
	int t=exgcd(b,a%b,x2,y2);
	x1=y2;
	y1=x2-(a/b)*y2;
	return t;  //返回gcd(a,b)
}

int main()
{
	int a,b,c;
	cin>>a>>b>>c;
	int l=c/exgcd(a,b,x1,y1);
	X=x1*l;
	Y=y1*l;
	cout<<X<<" "<<Y<<endl;
}


结束,蒟蒻鱼去补作业了

原文地址:https://www.cnblogs.com/XJack/p/10850148.html