原理
//一般gcd
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
当递归得到b=0时,得到gcd(a,b)=a,因此方程变为ax+0y=a,此时x=1,y=0是方程的一组特解
模板
void exgcd(ll a,ll b,ll &x,ll &y){
if(b==0) x=1,y=0;
else{
exgcd(b,a%b,y,x),y-=a/b*x;
}
}
例题
P5656 解二元一次不定方程
题意:
给定不定方程
ax+by=c
若该方程无整数解,输出 -1
若该方程有整数解,且有正整数解,则输出其正整数解的数量,所有正整数解中 x 的最小值,所有正整数解中 y的最小值,所有正整数解中 x 的最大值,以及所有正整数解中 y的最大值
若方程有整数解,但没有正整数解,你需要输出所有整数解中 x 的最小正整数值, y 的最小正整数值
解法:
用exgcd求出特解(x_0,y_0),该方程的通解为(x=x_0+frac{b}{g}t,y=y_0-frac{a}{g}t),求出x的最小正整数解,若此时y<=0,则方程有正整数解,否则无正整数解。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
void exgcd(ll a,ll b,ll &x,ll &y){
if(b==0) x=1,y=0;
else{
exgcd(b,a%b,y,x),y-=a/b*x;
}
}
int main (){
int T;
scanf("%d",&T);
while(T--){
ll a,b,c;
scanf("%lld%lld%lld",&a,&b,&c);
ll g=__gcd(a,b);
if(c%g!=0){
printf("-1
");
continue;
}
ll x,y;
exgcd(a,b,x,y);
x*=c/g,y*=c/g;
ll xmin,xmax,ymin,ymax;
ll xadd=b/g,yadd=a/g;
if(x<0){
xmin=x+xadd*((-x)/xadd+1);
}
else{
xmin=x-xadd*((x-1)/xadd);
}
if(y<0){
ymin=y+yadd*((-y)/yadd+1);
}
else{
ymin=y-yadd*((y-1)/yadd);
}
xmax=(c-b*ymin)/a;
ymax=(c-a*xmin)/b;
ll num=(xmax-xmin)/xadd+1;
if(ymax<=0){
printf("%lld %lld
",xmin,ymin);
}
else{
printf("%lld %lld %lld %lld %lld
",num,xmin,ymin,xmax,ymax);
}
}
}