刚刚写题以为是 e x g c d exgcd exgcd板子出问题了,就去洛谷上找到这个板子题搞一波
本题肯定是板子题,但是需要知道 e x g c d exgcd exgcd求出的最小整数解会有哪几种情况,因为 a , b , c a,b,c a,b,c均为正整数:
- x > 0 x>0 x>0, y < = 0 y<=0 y<=0
- x < = 0 x<=0 x<=0, y > 0 y>0 y>0
- x > 0 x>0 x>0, y > 0 y>0 y>0
先给出扩欧求二元一次不定方程的解释:已知 a x + b y = c ax+by=c ax+by=c,设 r = g c d ( a , b ) r=gcd(a,b) r=gcd(a,b),则
- 若 c % r ! = 0 c\%r!=0 c%r!=0,该方程组无整数解
- 若 c % r = = 0 c\%r==0 c%r==0,我们可以先求出 a x + b y = r ax+by=r ax+by=r对应的一组整数解 ( x 1 , y 1 ) (x_1,y_1) (x1,y1),然后再乘以 c c c并除以 r r r即可得到 a x + b y = c ax+by=c ax+by=c的最小整数解 x 0 = x 1 ∗ c / r , y 0 = y 1 ∗ c / r x_0=x_1*c/r,y_0=y_1*c/r x0=x1∗c/r,y0=y1∗c/r,那么其通解为 x = x 0 + k ∗ ( b / r ) , y = y 0 − k ∗ ( a / r ) x=x_0+k*(b/r),y=y_0-k*(a/r) x=x0+k∗(b/r),y=y0−k∗(a/r), k k k取任意整数;
上述最小整数解的含义是 x , y x,y x,y其中一个为最小正整数或者二者均是最小正整数。因此实际上通解的 x 0 , y 0 x_0,y_0 x0,y0必须是一个增大一个减小,一起变化的,因此不难想到分论讨论寻找范围
对于上述第一种情况,要知道是否有正整数解,就是看 x x x最多减去多少次仍大于0,并且计算 y y y最少加上多少次能大于0,对于得到这两个次数,分 d x > = d y dx>=dy dx>=dy和 d x < d y dx<dy dx<dy两种情况讨论,前者肯定有多个正整数解,后者不存在正整数解,然后就是细节计算了。第二种情况同理。至于第三种情况,是一定至少存在一组正整数解的,那么仍然按照上面的思想计算即可
//
// Created by Happig on 2020/8/21
//
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x, y) make_pair(x,y)
#define mem(a, x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double dinf = 1e300;
const ll INF = 1e18;
const int Mod = 1e9 + 7;
const int maxn = 2e5 + 10;
ll gcd(ll a, ll b) {
return !b ? a : gcd(b, a % b);
}
void exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) {
x = 1, y = 0;
return;
}
exgcd(b, a % b, y, x);
y -= (a / b) * x;
}
int main() {
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
//ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll a, b, c, x1, y1, mi_x, mi_y, ma_x, ma_y, cnt;
int t;
scanf("%d", &t);
while (t--) {
scanf("%lld%lld%lld", &a, &b, &c);
ll g = gcd(a, b);
if (c % g != 0) {
puts("-1");
} else {
exgcd(a, b, x1, y1);
ll x = x1 * c / g, y = y1 * c / g;
a /= g, b /= g;
if (x > 0 && y <= 0) {
ll dx = x / b - (x % b == 0), dy = abs(y) / a + 1;
if (dx >= dy) {
cnt = dx - dy + 1;
mi_x = x - dx * b, mi_y = y + dy * a;
ma_x = x - dy * b, ma_y = y + dx * a;
printf("%lld %lld %lld %lld %lld\n", cnt, mi_x, mi_y, ma_x, ma_y);
} else {
mi_x = x - dx * b, mi_y = y + dy * a;
printf("%lld %lld\n", mi_x, mi_y);
}
} else if (x <= 0 && y > 0) {
ll dx = abs(x) / b + 1, dy = y / a - (y % a == 0);
if (dy >= dx) {
cnt = dy - dx + 1;
mi_x = x + dx * b, mi_y = y - dy * a;
ma_x = x + dy * b, ma_y = y - dx * a;
printf("%lld %lld %lld %lld %lld\n", cnt, mi_x, mi_y, ma_x, ma_y);
} else {
mi_x = x + dx * b, mi_y = y - dy * a;
printf("%lld %lld\n", mi_x, mi_y);
}
} else {
ll dx = x / b - (x % b == 0), dy = y / a - (y % a == 0);
cnt = dx + dy;
mi_x = x - dx * b, mi_y = y - dy * a;
ma_x = x + dy * b, ma_y = y + dx * a;
printf("%lld %lld %lld %lld %lld\n", cnt, mi_x, mi_y, ma_x, ma_y);
}
}
}
return 0;
}