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;
}
结束,蒟蒻鱼去补作业了