题意:
给定a,b,c,求x,y,使得ax + by = c,题目保证有解,多解时另|x|+|y|最小,若还是多解则让|x|*a+|y|*b最小
思路:
首先交换一下a和b保证a>b(注意输出顺序也会受到影响),然后观察式子:
|x|+|y| = |x0+b/gcd(a,b)*t| + |y0 - a/gcd(a, b)*t|
因为我们规定a > b,所以式子的变化率主要由y决定,因此最小值应该在y=0左右,设t=y0*gcd(a,b)/a,那么枚举t-5,t+5之间的t值就能求出结果
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const long long INF = 1e18;
ll iabs(ll x) {
return (x > 0 ? x : -x);
}
ll exgcd(ll a, ll b, ll& x, ll& y) {
if (b == 0) {
x = 1, y = 0;
return a;
}
ll r = exgcd(b, a % b, y, x);
y -= a / b * x;
return r;
}
int main() {
ll a, b, c;
while (~scanf("%lld%lld%lld", &a, &b, &c) && (a || b || c)) {
bool flag = false;
if (a < b) {
swap(a, b);
flag = true;
}
ll x, y;
ll d = exgcd(a, b, x, y);
x *= c / d, y *= c / d;
ll t = y * d / a;
ll minv = INF, minsum = INF, ansx = 0, ansy = 0;
for (ll i = t - 5; i <= t + 5; i++) {
ll xx = iabs(x + b / d * i), yy = iabs(y - a / d * i);
if (xx + yy < minv) {
minv = xx + yy;
minsum = xx * a + yy * b;
ansx = xx;
ansy = yy;
}
else if (xx + yy == minv) {
if (xx * a + yy * b < minsum) {
minsum = xx * a + yy * b;
ansx = xx;
ansy = yy;
}
}
}
if (flag) printf("%lld %lld\n", ansy, ansx);
else printf("%lld %lld\n", ansx, ansy);
}
return 0;
}