版权声明,大部分摘抄于《信息学奥赛之数学一本通》 如有侵权行为,本文作者将删除
持续更新ing
辗转相除法用来求两个数的最大公约数,又称欧几里得算法,其原理是:GCD(x,y)=GCD(x,y-x);
代码实现
int GCD(int x,int y){
if(y==0) return x;
else return GCD(y,x%y);
}
定理:a,b两个数的最大公约数乘以它们的最小公倍数等于两数相乘
用来在已知(a,b)时,求解一组(p,q),使得p * a + q * b = GCD(a,b)
根据欧几里得算法可得,a和b都在减小,当b减小到0时,就可以得出p=1,q=0.然后递归回去就可以求出最终的p和q了。
代码实现
#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int exgcd(int a,int b,int &x,int &y){//加上&会改变下方调用x,y的值
int ret,tmp;
if(!b){
x=1;
y=0;
return a;
}
ret=exgcd(b,a%b,x,y);
tmp=x;
x=y;
y=tmp-a/b*y;
return ret;
}
int main(){
int a,b,x,y,z;
cin>>a>>b;
z=exgcd(a,b,x,y);//就是这里
cout<<z<<" "<<x<<" "<<y<<‘\n‘;
return 0;
}
定理1:对于方程a * x + b * y = c,该方程等价于a * c ≡ c (mod b),有整数解的充分必要条件是: c % GCD(a,b) = 0。
根据定理1,对于方程 a * x + b * y = c,我们可以先用扩展欧几里得算法求出一组x0,y0也就是 a * x0 + b * y0 = GCD(a,b),然后两边同时除以GCD(a,b),再乘以c。这样就得到了方程
a * x0 * c / GCD(a,b) + b * y0 * c / GCD(a,b) = c,我们也就找到了方程的一个解。
定理2:若GCD(a,b)=1,且x0,y0,为a * x+ b * y = c的一组解,则该方程的任一解可表示为:x = x0 + b * t ,y = y0 - a * t,且对任一整数t,皆成立。
根据定理2,可以求出方程的所有解。但实际问题中,我们往往被要求去求最小整数解,也就是求一个特解x,t = b / GCD(a,b),x = (x % t + t) % t。
代码实现
int exgcd(int a,int b,int &x,int &y){
if(b==0){
x=1;
y=0;
return a;
}
int d=exgcd(b,a%b,x,y);
int tmp=x;
x=y;
y=tmp-a/b*y;
return d;
} //用扩展欧几里得算法求解线性方程 ax+by=c;
bool get(int a,int b,int c,int &x,int &y){
int d=exgcd(a,b,x,y);
if(c%d) return false;
int k=c/d;
x*=k;
y*=k;
//求的只是其中一个解
return true;
}
原文:https://www.cnblogs.com/zxjg/p/11644043.html