洛谷 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。

posted @ 2021-05-14 15:46  尹昱钦  阅读(236)  评论(0编辑  收藏  举报