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.
Replace each interval by how far it still is from the borders: and . A move just decreases exactly one of these two numbers. Does that game smell suspiciously like something classic?
One interval with gaps is just a 2-pile Nim position, so its Grundy value is . With two intervals, the total position is losing exactly when the two interval Grundy values are equal.
So Alice does not really care about the exact interval, only about choosing some value . Any is achievable: take , , i.e. the interval .
For the random interval, count pairs with and . Introduce . Then and necessarily . For a fixed valid , each set bit of can go either to or to , so how many ordered pairs do you get?
The losing count for choosing Grundy is Count the last set with a standard binary digit DP on with states equal / already smaller. Then scan , pick the minimum, and output . Also, if , choose any and Alice wins with probability immediately.
This game is just Nim wearing an interval costume.
For one interval inside , define the two gaps A move decreases exactly one of or to any smaller nonnegative integer. That is literally a 2-heap Nim position, so its Grundy value is
For two intervals, the whole game is the disjoint sum of two such positions, hence the total Grundy value is
Alice loses iff this xor is , i.e. iff
So Alice only cares about choosing the Grundy value of her own interval. That is the first big aha. Everything else is decorative bullshit.
Let . Any value is achievable: just take
which corresponds to the interval
Therefore Alice should pick some minimizing the number of random intervals in whose Grundy value is also .
If , then she can even choose . But for the second interval we always have
so that can never appear. Then Alice wins with probability . Free candy.
For the random interval, set
Every valid interval corresponds bijectively to one pair with and .
We need
Now introduce
Using the identity
we get
Also, any bit set in cannot be set in , so
Conversely, fix any with . For every bit where has a , that bit must belong to exactly one of , giving choices independently per set bit. Therefore each valid creates exactly
ordered pairs .
So we get the clean formula
That is the whole counting problem. No black magic, just bits.
So we only need
This is a standard binary digit DP with two states:
equal: the processed prefix of is exactly equal to the processed prefix of ;less: the processed prefix is already smaller.At bit :
That gives an routine for , hence also for .
For each test case:
The total number of possible second intervals is
so the winning probability for Alice is
The denominator does not depend on her choice, so minimizing is exactly what we want.
Let . For each candidate we do one bit DP, and we scan all .
So the complexity per test case is
and over all test cases it is
which is easily fast enough since . Memory usage is .
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
ll count_free(int m, int mask) {
ll less = 0, eq = 1;
for (int b = 30; b >= 0; --b) {
ll nless = 0, neq = 0;
bool can1 = ((mask >> b) & 1) == 0;
// Already smaller than m: choose any allowed bit.
nless += less * (can1 ? 2LL : 1LL);
int mb = (m >> b) & 1;
if (mb == 0) {
// Must put 0 to stay <= m and keep equality.
neq += eq;
} else {
// Put 0 here -> becomes smaller.
nless += eq;
// Put 1 here -> stays equal, only if allowed by mask.
if (can1) neq += eq;
}
less = nless;
eq = neq;
}
return less + eq;
}
ll lose_count(int x2, int k) {
int n = x2 - 1;
if (k > n) return 0;
int m = (n - k) / 2;
return (1LL << __builtin_popcount((unsigned)k)) * count_free(m, k);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int x1, x2;
cin >> x1 >> x2;
// Guaranteed win: choose a Grundy value that interval 2 can never have.
if (x1 > x2) {
cout << x2 + 1 << ' ' << x1 << '\n';
continue;
}
ll best = (1LL << 62);
int bestk = 0;
for (int k = 0; k <= x1 - 1; ++k) {
ll cur = lose_count(x2, k);
if (cur < best) {
best = cur;
bestk = k;
}
}
// Realize Grundy bestk by taking a = bestk, b = 0.
cout << bestk + 1 << ' ' << x1 << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
ll count_free(int m, int mask) {
ll less = 0, eq = 1;
for (int b = 30; b >= 0; --b) {
ll nless = 0, neq = 0;
bool can1 = ((mask >> b) & 1) == 0;
// Already smaller than m: choose any allowed bit.
nless += less * (can1 ? 2LL : 1LL);
int mb = (m >> b) & 1;
if (mb == 0) {
// Must put 0 to stay <= m and keep equality.
neq += eq;
} else {
// Put 0 here -> becomes smaller.
nless += eq;
// Put 1 here -> stays equal, only if allowed by mask.
if (can1) neq += eq;
}
less = nless;
eq = neq;
}
return less + eq;
}
ll lose_count(int x2, int k) {
int n = x2 - 1;
if (k > n) return 0;
int m = (n - k) / 2;
return (1LL << __builtin_popcount((unsigned)k)) * count_free(m, k);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int x1, x2;
cin >> x1 >> x2;
// Guaranteed win: choose a Grundy value that interval 2 can never have.
if (x1 > x2) {
cout << x2 + 1 << ' ' << x1 << '\n';
continue;
}
ll best = (1LL << 62);
int bestk = 0;
for (int k = 0; k <= x1 - 1; ++k) {
ll cur = lose_count(x2, k);
if (cur < best) {
best = cur;
bestk = k;
}
}
// Realize Grundy bestk by taking a = bestk, b = 0.
cout << bestk + 1 << ' ' << x1 << '\n';
}
return 0;
}