洛谷 P5656 【模板】二元一次不定方程 (exgcd)
传送门
解题思路
先转化为:
ax+by=gcd(a,b)
exgcd板子,求出一组特解\(x_0\),\(y_0\)后,我们发现,可以将
\(x_0+\frac{kb}{gcd(a,b)}\)
\(y_0-\frac{ka}{gcd(a,b)}\)
所以可以得出,x的最小正整数解为\(((x-1)\%(b/gcd)+b/gcd)\%(b/gcd)+1\)
注意因为要求正整数而不是整数,所以x一开始要减1后面要加1。
因为abc都大于零,所以只需看x取最小正整数解时y的正负就可以判断方程是否有正整数解,看y同理。
AC代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<ctime>
using namespace std;
int T;
long long x,y;
int exgcd(long long a,long long b){
if(b==0){
x=1;
y=0;
return a;
}
int gcd=exgcd(b,a%b);
swap(x,y);
y=y-(a/b)*x;
return gcd;
}
int main(){
cin>>T;
while(T--){
long long a,b,c;
scanf("%lld%lld%lld",&a,&b,&c);
int gcd=exgcd(a,b);
if(c%gcd!=0){
printf("-1\n");
continue;
}
x*=c/gcd;
y*=c/gcd;
long long minx=((x-1)%(b/gcd)+b/gcd)%(b/gcd)+1,maxy=(c-minx*a)/b;
long long miny=((y-1)%(a/gcd)+a/gcd)%(a/gcd)+1,maxx=(c-miny*b)/a;
if(maxy<=0){
printf("%lld %lld\n",minx,miny);
continue;
}
printf("%lld %lld %lld %lld %lld\n",(maxx-minx)/(b/gcd)+1,minx,miny,maxx,maxy);
}
return 0;
}
注意开long long。