拓展欧几里得算法

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


最大公因数

众所周知,辗转相除法是解决两个数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;
}



原文地址:https://www.cnblogs.com/Mychael/p/8282890.html