P5656 【模板】二元一次不定方程 (exgcd)

\[ax+by=d\\ ax_1+by_1=c\\ x_1=\frac{x*c}{gcd(a,b)},y_1=\frac{y*c}{gcd(a,b)}\\ 对于最小正整数解有:x_1+\lambda\frac{b}{gcd(a,b)}>0\qquad y_1-\lambda\frac{a}{gcd(a,b)}>0\\ 解得:\left\lceil\frac{-x_1+1}{\frac{b}{gcd(a,b)}}\right\rceil\le\lambda\le\left\lfloor\frac{y_1-1}{\frac{a}{gcd(a,b)}}\right\rfloor \]

//正整数解:x>0,y>0
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while('0'<=ch&&ch<='9')x=(x<<3)+(x<<1)+ch-48,ch=getchar();
	return x*f;
}
ll exgcd(ll a,ll b,ll &x,ll &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	ll d=exgcd(b,a%b,y,x);
	y-=a/b*x;
	return d;
}
int main(){
	int T;
	ll a,b,c,d,x,y,tmp,l,r,X,Y;
	T=read();
	while(T--){
		a=read(),b=read(),c=read();
		d=exgcd(a,b,x,y);
		if(c%d!=0){
			puts("-1");
			continue;
		}
		tmp=c/d;
		x*=tmp,y*=tmp;
//		printf("x=%d y=%d\n",x,y);
		l=ceil((double)(-x+1)/(double)(b/d));
		r=floor((double)(y-1)/(double)(a/d));
		if(l>r){
			printf("%lld %lld\n",x+l*(b/d),y-r*(a/d));
		}
		else{
			printf("%lld ",(r-l+1));
			X=x+l*(b/d);
			Y=y-r*(a/d);
			printf("%lld %lld ",X,Y);
		
			printf("%lld %lld\n",(c-b*Y)/a,(c-a*X)/b);
		}
	}
	return 0;
}
posted on 2022-09-26 14:32  Bwzhh  阅读(30)  评论(0编辑  收藏  举报