拓展欧几里得算法

来源:互联网 发布:apache配置文件路径 编辑:程序博客网 时间:2024/06/04 18:05

拓展欧几里得算法是用来解决不定方程的整数解的算法


最大公因数

众所周知,辗转相除法是解决两个数a,b的最大公因数的方法,记作gcd(a,b)
每次用a MOD b ,然后将b和模得的数再继续模下去,知道模数为0,也就是b|a
写成代码是:
int gcd(int a,int b){retrun b==0 ? a:gcd(b,a%b);}

很简短吧

拓展欧几里得算法

现在才是本文的重点
对于一个关于x和y的方程ax+by=c,我们知道这是一个不定方程,也就是说它的解不唯一

我们只研究整数解的情况,那么这个方程要么没有整数解,要么有无数个整数解

如何解?
1、求解ax+by=gcd(a,b)
本人很弱,不会证明,所以只给出过程。
在gcd过程中,当b=0时,x=1,y=0
否则x=y',y=x'-(a/b)*y'
这里的除法为整除
下面是实现代码:
void exgcd(int a,int b,int& d,int& x,int& y){if(b==0){d=a;x=1;y=0;}else exgcd(b,a%b,d,y,x),y-=(a/b)*x;}

2、等式两边乘以c/gcd(a,b)
我们发现,当上一个方程进行这个操作之后,就会变成我们想要的方程的形式
a*x*c/gcd+b*y*c/gcd=c
为了保证整数,当c%gcd!=0时,方程无整数解
若有解,x=x*c/gcd,y=y*c/gcd

3、解的周期
令b0=b/gcd,a0=a/gcd;
那么
x'=x+k*b0
y'=y-k*a0
就是所有的解
其中x的最小整数解是(x%b0+b0)%b0

完整求x最小整数解代码:
#include<iostream>#include<cstdio>#include<algorithm>using namespace std;void exgcd(int a,int b,int& d,int& x,int& y){if(!b) {d=a;x=1;y=0;}else exgcd(b,a%b,d,y,x),y-=(a/b)*x;}int main(){int a,b,c,x,y,b0,d;cin>>a>>b>>c;exgcd(a,b,d,x,y);if(c%d) cout<<"No solution!"<<endl;else{x=x*c/d;b0=b/d;cout<<(x%b0+b0)%b0<<endl;}return 0;}



原创粉丝点击