【模板】二元一次不定方程 (exgcd)
题目描述
给定不定方程
a x + b y = c ax+by=c ax+by=c
若该方程无整数解,输出
−
1
-1
−1。
若该方程有整数解,且有正整数解,则输出其正整数解的数量,所有正整数解中
x
x
x 的最小值,所有正整数解中
y
y
y 的最小值,所有正整数解中
x
x
x 的最大值,以及所有正整数解中
y
y
y 的最大值。
若方程有整数解,但没有正整数解,你需要输出所有整数解中
x
x
x 的最小正整数值,
y
y
y 的最小正整数值。
正整数解即为
x
,
y
x, y
x,y 均为正整数的解,
0
\boldsymbol{0}
0 不是正整数。
整数解即为
x
,
y
x,y
x,y 均为整数的解。
x
x
x 的最小正整数值即所有
x
x
x 为正整数的整数解中
x
x
x 的最小值,
y
y
y 同理。
输入格式
第一行一个正整数 T T T,代表数据组数。
接下来 T T T 行,每行三个由空格隔开的正整数 a , b , c a, b, c a,b,c。
输出格式
T T T 行。
若该行对应的询问无整数解,一个数字
−
1
-1
−1。
若该行对应的询问有整数解但无正整数解,包含
2
2
2 个由空格隔开的数字,依次代表整数解中,
x
x
x 的最小正整数值,
y
y
y 的最小正整数值。
否则包含
5
5
5 个由空格隔开的数字,依次代表正整数解的数量,正整数解中,
x
x
x 的最小值,
y
y
y 的最小值,
x
x
x 的最大值,
y
y
y 的最大值。
读入输出量较大,注意使用较快的读入输出方式
样例 #1
样例输入 #1
7
2 11 100
3 18 6
192 608 17
19 2 60817
11 45 14
19 19 810
98 76 5432
样例输出 #1
4 6 2 39 8
2 1
-1
1600 1 18 3199 30399
34 3
-1
2 12 7 50 56
提示
【数据范围】
对于 100 % 100\% 100% 的数据, 1 ≤ T ≤ 2 × 10 5 1 \le T \le 2 \times {10}^5 1≤T≤2×105, 1 ≤ a , b , c ≤ 10 9 1 \le a, b, c \le {10}^9 1≤a,b,c≤109。
使用扩展欧几里得算法求出特解和通解,用通解的大于等于1的不等式计算得到k的取值范围,根据一元函数的性质进行计算最值即可
#include<iostream>
using namespace std;
typedef long long ll;
ll a, b, c, T;
ll exgcd(ll a, ll b, ll& x, ll& y){
if(b == 0){
x = 1;
y = 0;
return a;
}
ll x1;
ll g = exgcd(b, a%b, x1, x);
y = x1-a/b*x;
return g;
}
inline ll read(){
char ch = getchar();
ll x = 0;
int f = 1;
while(ch < '0' || ch > '9'){
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x*10+ch-'0';
ch = getchar();
}
return x*f;
}
int main(){
cin >> T;
while(T--){
a = read(), b = read(), c = read();
ll x, y, g;
g = exgcd(a, b, x, y);
if(c % g != 0){
cout << -1 << endl;
continue;
}
x = x*c/g, y = y*c/g;
ll l = (1-y)*g/a, r = (x-1)*g/b; //这个过程很重要
if((x-1)*g % b != 0 && x < 1) r--; //判断一个式子正负要用过程可能为负的判断,因为结果会自动取整
if((1-y)*g % a != 0 && y < 1) l++;//比如-2/3 = 0
// while(y+l*a/g <= 0)l++; //这样写也可以
// while(x-r*b/g <= 0)r--;
if(r-l+1 <= 0){
printf("%lld %lld\n", x-r*b/g, y+l*a/g);
}
else{
printf("%lld %lld %lld %lld %lld\n", r-l+1, (x-r*b/g), (y+l*a/g), (x-l*b/g), (y+r*a/g));
}
}
return 0;
}