ZOJ 3593 One Person Game 扩展欧几里得
在数轴上,需要从A到B,每次可以向左或向右走,求最小的步数。
使用扩欧,对于的通解
根据题设,答案分为两种情况:
利用基本不等式可证得,当且仅当时有答案最小。
故令,有,因为题目要求整点,所以在t的两边找答案即可。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#define inf (long long) 0x7fffffff
#define ll long long
typedef std::pair<int, int> pii;
typedef std::pair<ll, ll> pll;
typedef long long LL;
ll gcd(ll p, ll q) { return q == 0 ? p : gcd(q, p % q); }
using namespace std;
const int N = 1e6 + 10;
typedef std::pair<int, int> pii;
ll x, y;
ll Abs(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 -= x * (a / b);
return r;
}
int main() {
ll a, b, c,A, B;
int T;
cin >> T;
while (T--) {
cin >> A >> B >> a >> b;
c = A > B ? A - B : B - A;
ll d = gcd(a, b);
if (c % d != 0) {
cout << -1 << endl;
continue;
}
a/=d;
b/=d;
exgcd(a,b,x,y);
x *= c / d;
y *= c / d;
ll t = (y - x) / (a + b);
LL ans = inf;
for (ll i = t - 1; i <= t + 1; i++) {
ll tx = x + b * i;
ll ty = y - a * i;
ll tmp;
if (Abs(tx) + Abs(ty) == Abs(tx + ty))
tmp = max(Abs(tx), Abs(ty));
else
tmp = Abs(tx) + Abs(ty);
ans = min(ans, tmp);
}
cout << ans << endl;
}
return 0;
}
浙公网安备 33010602011771号