题意:
给定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; }