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.
Think about the highest set bit. Since , can never have a bit above the highest set bit of the current .
That means the highest set bit of can never move upward. So if needs a higher bit than the initial has, it is straight-up impossible.
If , then one operation with finishes immediately. The annoying cases are exactly when that XOR value is numerically larger than .
Let be the highest power of two not exceeding . If has the same highest bit as , then has no bit , so it is less than .
If has a smaller highest bit, first make become using . Then , so one more operation reaches .
Let the current value be . In one move we choose some with , then replace
The whole problem is about the numeric restriction . XOR itself is easy; the constraint is where the trap lives.
The Main Invariant
Look at the highest set bit of .
If the highest set bit of is at position , then . Since , we also have , so has no bit above position .
Therefore also cannot have any bit above position .
So the highest set bit can stay the same or go down, but it can never go up. No magic, no loophole, no XOR wizardry. If has a higher set bit than the initial , the answer is impossible.
Formally, if
print .
Now Show Everything Else Is Possible
Let
so is the highest power of two not exceeding the initial .
There are two useful cases.
Case 1: and have the same highest bit
Then both numbers contain bit .
So in , that bit cancels out. This means
And since , we get
So the direct move works:
Then
One operation. Clean.
Case 2: has a smaller highest bit
Directly using might fail because it can be larger than . Example-style nonsense happens here.
Instead, first turn into the all-ones number with the same highest bit:
This number looks like
from bit through the highest bit of .
Can we move from to in one operation? Yes. Choose
Since and both have the highest bit , that bit cancels in , so
Thus the move is legal, and after it we have .
Now move from to . Choose
Because in this case, and has the highest bit , the value still has highest bit , but it is not equal to unless . Since the constraints have , we get
So , meaning the second move is legal.
Then
So two operations always suffice.
Construction Summary
For each test case:
This uses at most operations, way below the limit of . The limit is basically there for vibes.
Correctness Proof
We prove the algorithm prints a valid answer exactly when one exists.
First, suppose has a higher highest set bit than the initial . During any operation, , so has no bit above the highest set bit of . Therefore also has no bit above that position. Thus the highest set bit can never increase. So reaching such a is impossible, and printing is correct.
Now suppose does not have a higher highest set bit than .
If , zero operations are valid.
If , choosing is legal, and the new value becomes . So the one-operation output is valid.
Otherwise, define as the highest power of two not exceeding , and define .
The first printed value is . Since and share the same highest bit , that bit is not set in , so . Hence the first operation is legal and changes to .
The second printed value is . Since has no bit above the highest bit of , this XOR also has no bit above it. Also, because , at least one low bit of is flipped from to , so . Hence , and the second operation is legal. It changes to .
Thus whenever the algorithm does not print , its sequence is legal and reaches . Combined with the impossibility argument, the algorithm is correct.
Complexity
Each test case does only a constant amount of bit work.
time per test case, and extra memory.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
ll a, b;
cin >> a >> b;
if (a == b) {
cout << 0 << '\n';
cout << '\n';
continue;
}
int ma = 63 - __builtin_clzll(a);
int mb = 63 - __builtin_clzll(b);
if (mb > ma) {
cout << -1 << '\n';
continue;
}
ll direct = a ^ b;
if (direct <= a) {
cout << 1 << '\n';
cout << direct << '\n';
continue;
}
ll p = 1LL << ma;
ll full = 2 * p - 1;
cout << 2 << '\n';
cout << (a ^ full) << ' ' << (full ^ b) << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
ll a, b;
cin >> a >> b;
if (a == b) {
cout << 0 << '\n';
cout << '\n';
continue;
}
int ma = 63 - __builtin_clzll(a);
int mb = 63 - __builtin_clzll(b);
if (mb > ma) {
cout << -1 << '\n';
continue;
}
ll direct = a ^ b;
if (direct <= a) {
cout << 1 << '\n';
cout << direct << '\n';
continue;
}
ll p = 1LL << ma;
ll full = 2 * p - 1;
cout << 2 << '\n';
cout << (a ^ full) << ' ' << (full ^ b) << '\n';
}
}