零坐标的操作是强制的,可以预处理
2026-09-19 18:47:33
发布于:浙江
3阅读
0回复
0点赞
第一次问题在相遇检测这里的条件写反了

应改为:
auto A = pos[i], B = mix[j];
if (A.second.fixed) {
swap(A.first, A.second);
swap(B.first, B.second);
}
// 这里必须保留 fixed,而不是跳过 fixed
if (!A.first.fixed) continue;
错误写法是:
if (A.first.fixed) continue;
因为交换后 A.first 正常情况下本来就应该是固定值;写成跳过会丢弃几乎所有有效匹配,所以会出现大量 WA
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
static inline bool sgn(ll x) { return x > 0; }
struct Obj {
bool fixed;
ll cost, inc, st, en;
Obj(ll x, ll y) : fixed(true), cost(y), inc(0), st(x), en(x) {}
Obj(ll a, ll b, ll c, ll d) : fixed(false), cost(d), inc(b), st(a), en(c) {
if (st == en) fixed = true, inc = 0;
}
};
// Return a common value of two compressed arithmetic trajectories.
// If try_val >= 0, force the common value to be try_val.
ll compat(Obj a, Obj b, ll try_val = -1) {
if (a.fixed != b.fixed && !a.fixed) swap(a, b);
if (a.fixed && b.fixed) {
if (try_val >= 0 && try_val != a.st) return -1;
return a.st == b.st ? a.st : -1;
}
if (a.fixed || b.fixed) {
if (b.fixed) swap(a, b);
if (try_val >= 0 && a.st != try_val) return -1;
ll l = min(b.st, b.en), r = max(b.st, b.en);
ll mod = llabs(b.inc);
if (a.st < l || a.st > r || (a.st % mod) != (l % mod)) return -1;
return a.st;
}
ll al = min(a.st, a.en), ar = max(a.st, a.en);
ll bl = min(b.st, b.en), br = max(b.st, b.en);
if (try_val >= 0) {
if (al % llabs(a.inc) != try_val % llabs(a.inc) ||
bl % llabs(b.inc) != try_val % llabs(b.inc) ||
try_val < al || try_val > ar || try_val < bl || try_val > br)
return -1;
return try_val;
}
if (llabs(a.inc) != llabs(b.inc) ||
al % llabs(a.inc) != bl % llabs(b.inc)) return -1;
ll v = min(ar, br);
return v < max(al, bl) ? -1 : v;
}
ll solve(vector<ll> x, vector<ll> y) {
ll ans0 = 0;
if (x == y) return 0;
// Remove zero coordinates at the beginning/end; these moves are forced.
for (int i = 0; i < 2; ++i) if (x[i] == 0) x[i] += x[1-i], ++ans0;
if (ans0 == 2) return -1;
if (x == y) return ans0;
ll zc = 0;
for (int i = 0; i < 2; ++i) if (y[i] == 0) y[i] -= y[1-i], ++ans0, ++zc;
if (zc == 2) return -1;
if (x == y) return ans0;
// Same-sign case: ordinary reverse Euclidean algorithm.
if ((x[0] > 0) == (x[1] > 0)) {
if (x[0] < 0) for (int i = 0; i < 2; ++i) x[i] = -x[i], y[i] = -y[i];
if (min(y[0], y[1]) <= 0) return -1;
while (y[0] >= x[0] && y[1] >= x[1] &&
x[0] + x[1] != y[0] + y[1] && min(y[0], y[1]) > 0) {
if (y[0] == y[1]) break;
if (y[0] > y[1]) {
ll k = (y[0] - max(x[0], y[1]) - 1) / y[1] + 1;
y[0] -= y[1] * k; ans0 += k;
} else {
ll k = (y[1] - max(x[1], y[0]) - 1) / y[0] + 1;
y[1] -= y[0] * k; ans0 += k;
}
}
return x == y ? ans0 : -1;
}
// Opposite signs must be compatible coordinate-wise.
if (sgn(x[0]) != sgn(y[0]) && sgn(x[1]) != sgn(y[1])) return -1;
// Both coordinates keep their signs: reverse Euclidean on absolute values.
if (sgn(x[0]) == sgn(y[0]) && sgn(x[1]) == sgn(y[1])) {
if (x[0] < 0) for (int i = 0; i < 2; ++i) x[i] = -x[i], y[i] = -y[i];
x[1] = llabs(x[1]); y[1] = llabs(y[1]);
while (y[0] <= x[0] && y[1] <= x[1] &&
x[0] + x[1] != y[0] + y[1]) {
if (x[0] == x[1]) break;
if (x[0] > x[1]) {
ll k = max(0LL, x[0] - max(x[1], y[0]) - 1) / x[1] + 1;
x[0] -= x[1] * k; ans0 += k;
} else {
ll k = max(0LL, x[1] - max(x[0], y[1]) - 1) / x[0] + 1;
x[1] -= x[0] * k; ans0 += k;
}
}
return x[0] == y[0] && x[1] == y[1] ? ans0 : -1;
}
// Normalize to x0>0, x1<0, y0>0, y1>0: the second coordinate crosses zero.
if (sgn(x[0]) != sgn(y[0])) swap(x[0], x[1]), swap(y[0], y[1]);
if (x[0] < 0) for (int i = 0; i < 2; ++i) x[i] = -x[i], y[i] = -y[i];
if (!(x[0] > 0 && y[0] > 0 && x[1] < 0 && y[1] > 0)) return -1;
vector<pair<Obj,Obj>> pos, mix;
ll base = ans0;
// Backward compressed trajectories from y while both coordinates are positive.
ll cnt = 0;
while (y[0] > 0 && y[1] > 0) {
if (y[0] == y[1]) { pos.push_back({Obj(y[0],cnt), Obj(y[1],cnt)}); break; }
if (y[0] > y[1]) {
ll k = (y[0] - y[1] - 1) / y[1] + 1;
pos.push_back({Obj(y[0], -y[1], y[0]-y[1]*(k-1), cnt), Obj(y[1],cnt)});
y[0] -= y[1]*k; cnt += k;
} else {
ll k = (y[1] - y[0] - 1) / y[0] + 1;
pos.push_back({Obj(y[0],cnt), Obj(y[1],-y[0],y[1]-y[0]*(k-1),cnt)});
y[1] -= y[0]*k; cnt += k;
}
}
// Forward compressed trajectories from x until the second coordinate becomes positive.
cnt = 0;
while (x[0] > 0) {
if (x[1] >= 0) {
if (x[1] == 0) ++cnt, x[1] = x[0];
mix.push_back({Obj(x[0],cnt), Obj(x[1],cnt)}); break;
}
if (llabs(x[0]) == llabs(x[1])) {
x[1] = x[0]; cnt += 2;
mix.push_back({Obj(x[0],cnt), Obj(x[1],cnt)}); break;
}
if (x[0] > llabs(x[1])) {
ll k = (x[0] - llabs(x[1]) - 1) / llabs(x[1]) + 1;
mix.push_back({Obj(x[0],x[1],x[0]+x[1]*(k-1),cnt+1),
Obj(x[1]+x[0],x[1],x[1]+x[0]+x[1]*(k-1),cnt+1)});
x[0] += x[1]*k; cnt += k;
} else {
ll k = (llabs(x[1]) - x[0] - 1) / x[0] + 1;
x[1] += x[0]*k; cnt += k;
}
}
const ll INF = (ll)2e18 + 10;
ll ret = INF; int p = 0;
for (int i = 0; i < (int)pos.size(); ++i) {
for (int j = p; j < (int)mix.size(); ++j) {
ll posMin = pos[i].first.en + pos[i].second.en;
ll posMax = pos[i].first.st + pos[i].second.st;
ll mixMin = mix[j].first.en + mix[j].second.en;
ll mixMax = mix[j].first.st + mix[j].second.st;
if (posMin > mixMax) break;
if (j == p && mixMin > posMax) { ++p; continue; }
auto A = pos[i], B = mix[j];
if (A.second.fixed) swap(A.first,A.second), swap(B.first,B.second);
if (!A.first.fixed) continue;
ll v0 = compat(A.first,B.first);
if (v0 < 0) continue;
ll meet = -1;
if (!B.first.fixed) {
ll it = (v0 - B.first.st) / B.first.inc;
meet = B.second.st + it * B.second.inc;
if (compat(A.second,B.second,meet) < 0) continue;
} else {
meet = compat(A.second,B.second);
if (meet < 0) continue;
}
ll cur = A.first.cost + B.first.cost;
ll m0 = 0, m1 = 0;
if (A.first.inc) m0 = (v0 - A.first.st) / A.first.inc;
else if (A.second.inc) m0 = (meet - A.second.st) / A.second.inc;
if (B.first.inc) m1 = (v0 - B.first.st) / B.first.inc;
else if (B.second.inc) m1 = (meet - B.second.st) / B.second.inc;
ret = min(ret, cur + m0 + m1);
}
}
return ret == INF ? -1 : base + ret;
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr);
int Q; cin >> Q;
while (Q--) { ll a,b,c,d; cin >> a >> b >> c >> d; cout << solve({a,b},{c,d}) << '\n'; }
}
这里空空如也



有帮助,赞一个