Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
The only annoying part is the absolute value. Split the world into four cases: whether is below or above , and whether is below or above .
Inside one fixed case, the objective becomes linear. For example, if and , then , so you only need to minimize plus constants.
Now think digit DP over bits. At each bit, can only be one of because .
To enforce , , , or , process bits from high to low and keep a comparison state: equal so far, already smaller, or already larger.
Run the DP for all four sign cases. Each DP minimizes a signed bit-sum under the required comparisons, then reconstructs the best among the four candidates.
The condition means every bit can belong to at most one of the two numbers. So for each bit we may choose exactly one of
The trap is assuming bits are independent for the distance. They are not, because depends on the highest bit where and differ. So don't do local “fix bad common bits” hacks; carries and comparisons will clown on you.
Instead, remove the absolute values by trying all four order cases:
For a fixed case, the objective becomes linear. Let
Then inside that case,
where the terms involving are constants. So we only need to minimize
subject to:
Now this is a standard bit DP.
Process bits from high to low. We need enough bits to allow answers up to below , so bits are enough because and the statement guarantees a valid optimal answer within this range.
For each number, keep its comparison with the target prefix:
A DP state is
meaning after deciding all bits above , the current prefix of compares to as , and the current prefix of compares to as . The value stored is the minimum signed contribution already paid.
When choosing bit , try:
The contribution is
The comparison state updates normally:
After all bits are chosen, only states satisfying the selected order case are allowed. For example:
Among valid final states, take the minimum DP value for that case, reconstruct , and compute the real distance
Finally, try all four cases and output the pair with smallest real distance.
Why this works:
Every feasible pair has exactly one relationship to each target: or both include equality, and same for . So the pair appears in at least one of the four cases. In any fixed case, the DP enumerates every bit assignment satisfying and the required comparisons. Since the absolute-value objective is linear inside that case, minimizing the signed bit-sum is exactly minimizing the original distance among pairs in that case. Taking the best result over all four cases therefore gives a global optimum.
Edge cases are clean:
There are only bits, comparison states, transitions per state, and sign cases. So each test case is tiny:
time, and memory, or just constant memory plus parent pointers for reconstruction.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
struct Parent {
int pc = -1, qc = -1, pb = 0, qb = 0;
};
int updCmp(int cmp, int bit, int target) {
if (cmp != 0) return cmp;
if (bit < target) return 1;
if (bit > target) return 2;
return 0;
}
bool okCmp(int cmp, bool needGreater) {
return needGreater ? (cmp != 1) : (cmp != 2);
}
pair<ll, ll> solveCase(ll x, ll y, bool pGreater, bool qGreater) {
const ll INF = (1LL << 60);
const int B = 30;
int sp = pGreater ? 1 : -1;
int sq = qGreater ? 1 : -1;
vector<vector<vector<ll>>> dp(B + 2, vector<vector<ll>>(3, vector<ll>(3, INF)));
vector<vector<vector<Parent>>> par(B + 1, vector<vector<Parent>>(3, vector<Parent>(3)));
dp[B + 1][0][0] = 0;
for (int i = B; i >= 0; --i) {
int xb = (x >> i) & 1;
int yb = (y >> i) & 1;
ll w = 1LL << i;
for (int cp = 0; cp < 3; ++cp) {
for (int cq = 0; cq < 3; ++cq) {
ll cur = dp[i + 1][cp][cq];
if (cur >= INF) continue;
for (auto [pb, qb] : {pair<int,int>{0,0}, {1,0}, {0,1}}) {
int np = updCmp(cp, pb, xb);
int nq = updCmp(cq, qb, yb);
ll val = cur + w * (sp * pb + sq * qb);
if (val < dp[i][np][nq]) {
dp[i][np][nq] = val;
par[i][np][nq] = {cp, cq, pb, qb};
}
}
}
}
}
ll best = INF;
int bp = -1, bq = -1;
for (int cp = 0; cp < 3; ++cp) {
for (int cq = 0; cq < 3; ++cq) {
if (!okCmp(cp, pGreater) || !okCmp(cq, qGreater)) continue;
if (dp[0][cp][cq] < best) {
best = dp[0][cp][cq];
bp = cp;
bq = cq;
}
}
}
ll p = 0, q = 0;
int cp = bp, cq = bq;
for (int i = 0; i <= B; ++i) {
Parent pa = par[i][cp][cq];
if (pa.pb) p |= 1LL << i;
if (pa.qb) q |= 1LL << i;
cp = pa.pc;
cq = pa.qc;
}
return {p, q};
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
ll x, y;
cin >> x >> y;
ll best = (1LL << 62), ansP = 0, ansQ = 0;
for (bool pg : {false, true}) {
for (bool qg : {false, true}) {
auto [p, q] = solveCase(x, y, pg, qg);
ll dist = llabs(x - p) + llabs(y - q);
if ((p & q) == 0 && dist < best) {
best = dist;
ansP = p;
ansQ = q;
}
}
}
cout << ansP << ' ' << ansQ << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
struct Parent {
int pc = -1, qc = -1, pb = 0, qb = 0;
};
int updCmp(int cmp, int bit, int target) {
if (cmp != 0) return cmp;
if (bit < target) return 1;
if (bit > target) return 2;
return 0;
}
bool okCmp(int cmp, bool needGreater) {
return needGreater ? (cmp != 1) : (cmp != 2);
}
pair<ll, ll> solveCase(ll x, ll y, bool pGreater, bool qGreater) {
const ll INF = (1LL << 60);
const int B = 30;
int sp = pGreater ? 1 : -1;
int sq = qGreater ? 1 : -1;
vector<vector<vector<ll>>> dp(B + 2, vector<vector<ll>>(3, vector<ll>(3, INF)));
vector<vector<vector<Parent>>> par(B + 1, vector<vector<Parent>>(3, vector<Parent>(3)));
dp[B + 1][0][0] = 0;
for (int i = B; i >= 0; --i) {
int xb = (x >> i) & 1;
int yb = (y >> i) & 1;
ll w = 1LL << i;
for (int cp = 0; cp < 3; ++cp) {
for (int cq = 0; cq < 3; ++cq) {
ll cur = dp[i + 1][cp][cq];
if (cur >= INF) continue;
for (auto [pb, qb] : {pair<int,int>{0,0}, {1,0}, {0,1}}) {
int np = updCmp(cp, pb, xb);
int nq = updCmp(cq, qb, yb);
ll val = cur + w * (sp * pb + sq * qb);
if (val < dp[i][np][nq]) {
dp[i][np][nq] = val;
par[i][np][nq] = {cp, cq, pb, qb};
}
}
}
}
}
ll best = INF;
int bp = -1, bq = -1;
for (int cp = 0; cp < 3; ++cp) {
for (int cq = 0; cq < 3; ++cq) {
if (!okCmp(cp, pGreater) || !okCmp(cq, qGreater)) continue;
if (dp[0][cp][cq] < best) {
best = dp[0][cp][cq];
bp = cp;
bq = cq;
}
}
}
ll p = 0, q = 0;
int cp = bp, cq = bq;
for (int i = 0; i <= B; ++i) {
Parent pa = par[i][cp][cq];
if (pa.pb) p |= 1LL << i;
if (pa.qb) q |= 1LL << i;
cp = pa.pc;
cq = pa.qc;
}
return {p, q};
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
ll x, y;
cin >> x >> y;
ll best = (1LL << 62), ansP = 0, ansQ = 0;
for (bool pg : {false, true}) {
for (bool qg : {false, true}) {
auto [p, q] = solveCase(x, y, pg, qg);
ll dist = llabs(x - p) + llabs(y - q);
if ((p & q) == 0 && dist < best) {
best = dist;
ansP = p;
ansQ = q;
}
}
}
cout << ansP << ' ' << ansQ << '\n';
}
}