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.
First ignore the lower bounds. If every color only has an upper cap , ask for the parity of rooted colored trees whose path-count vector never exceeds .
At any node, for each color except the parent edge color, there is either no child of that color or exactly one child of that color. So the counting recurrence is a product of terms .
Modulo , that product says: the current state has odd count iff every legal child state has even count. That is exactly the losing-state recurrence of a game where a move decrements one positive pile, and you may not use the same color as the previous move.
For the starting game state, the losing positions are exactly those with even total sum and no pile strictly larger than half the total. If one pile is too large, keep playing it; otherwise the second player can preserve balance after every pair of moves.
Use inclusion-exclusion for the lower bounds. Each color contributes an endpoint , or when . Now count endpoint choices with even sum and no strict majority. Bad choices have one unique endpoint greater than the rest, and the subset sums of optional deltas are handled by over , with .
The first move is to stop trying to draw the trees. The tree part looks huge, but modulo it collapses into a small take-away game. Nice little scam.
Fix only upper bounds for all colors. Let be the parity of the number of possible rooted subtrees when the edge to the parent has color . For the real root, use a fake color that forbids nothing.
At a node, because two incident edges cannot have the same color, for every color we may choose either:
So, modulo ,
This means iff all legal next states have value . That is exactly the recurrence for losing positions in this game:
For the starting state, there is no previous color. The starting state is losing exactly when
Why? If some pile has size , the first player plays that color. Whenever the opponent plays some other color, the first player plays the huge color again. The other colors run out first, so the opponent gets stuck. If no pile is too large and is odd, the first player removes from a maximum pile, leaving an even balanced state. If the state is even and balanced, the second player can always answer the first player's move by removing a currently too-large pile if one appears, otherwise any legal pile. After each pair of moves the position is balanced again. Eventually all tokens are consumed after an even number of moves, so the player to move first loses.
Therefore, for upper bounds , the parity is just the indicator of an even balanced vector. No trees anymore. The forest has been legally deleted.
Now restore the lower bounds. By inclusion-exclusion over the conditions , the answer is the xor over endpoint choices
where
For each chosen vector , we add
So we need the parity of endpoint choices with even sum and no strict majority.
Let
and let
For colors with , choosing instead of adds
Define the subset-sum polynomial over :
A choice has total sum , where is a subset sum represented by .
First count all even-sum choices. If there are no optional colors, this contributes iff is even. If there is at least one optional color, the parity is only in the very specific case where there is exactly one optional color and its is odd. Everything else gives an even number of even-sum choices.
Now subtract the bad even choices, where one selected endpoint is strictly greater than the sum of all others. Since the total is even, the other side has the same parity as that endpoint, so a strict inequality becomes a same-parity prefix ending two below the threshold.
Let
with for .
For a mandatory color , the endpoint is . It is a strict majority iff
so its contribution is
For an optional color, write and . If we excluded this color from , the low endpoint and high endpoint would seem to need two separate prefix queries. But they combine cleanly:
The shifted part of exactly accounts for the low-endpoint case, so the xor of the low and high bad cases is just
That is the key implementation trick. No per-color polynomial division, no nonsense.
We only need coefficients up to . For every query, the index is at most after subtracting the base outside the chosen color; negative indices simply contribute .
To build , count how many factors appear. Over ,
So while scanning , carry pairs of factors from to , and if one factor remains, multiply the bitset polynomial by using
Finally convert into the same-parity prefix array by doing
Then each query is just one bit lookup.
Complexity per test case is
where is the machine word size used by the bitset. Memory is , and the given total bounds are exactly built for this.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const int MAXM = 200000;
int main() {
setIO();
int T;
cin >> T;
bitset<MAXM + 1> poly;
while (T--) {
int n;
cin >> n;
vector<int> l(n), r(n);
int m = 0;
for (int i = 0; i < n; ++i) {
cin >> l[i] >> r[i];
m = max(m, r[i]);
}
vector<int> cnt(m + 1, 0);
ll base = 0;
int mandatoryParity = 0;
int optionalSignal = 0; // 0: none, 1: exactly one odd delta, 2: all other cases
for (int i = 0; i < n; ++i) {
if (l[i] == 0) {
base += r[i];
mandatoryParity ^= (r[i] & 1);
} else {
base += l[i] - 1;
int delta = r[i] - l[i] + 1;
++cnt[delta];
int add = ((l[i] & 1) == (r[i] & 1) ? 1 : 2);
optionalSignal = min(2, optionalSignal + add);
}
}
poly.reset();
poly[0] = 1;
for (int k = 1; k <= m; ++k) {
if (2 * k <= m) cnt[2 * k] += cnt[k] / 2;
if (cnt[k] & 1) poly ^= (poly << k);
}
for (int i = 2; i <= m; ++i) poly[i] = poly[i] ^ poly[i - 2];
auto pref = [&](ll x) -> int {
ll idx = x - base;
if (idx < 0 || idx > m) return 0;
return poly[(int)idx];
};
int bad = 0;
for (int i = 0; i < n; ++i) {
if (l[i] == 0) bad ^= pref(2LL * r[i] - 2);
else bad ^= pref((ll)l[i] + r[i] - 3);
}
int totalEven;
if (optionalSignal == 0) totalEven = mandatoryParity ^ 1;
else totalEven = (optionalSignal == 1);
cout << (bad ^ totalEven) << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const int MAXM = 200000;
int main() {
setIO();
int T;
cin >> T;
bitset<MAXM + 1> poly;
while (T--) {
int n;
cin >> n;
vector<int> l(n), r(n);
int m = 0;
for (int i = 0; i < n; ++i) {
cin >> l[i] >> r[i];
m = max(m, r[i]);
}
vector<int> cnt(m + 1, 0);
ll base = 0;
int mandatoryParity = 0;
int optionalSignal = 0; // 0: none, 1: exactly one odd delta, 2: all other cases
for (int i = 0; i < n; ++i) {
if (l[i] == 0) {
base += r[i];
mandatoryParity ^= (r[i] & 1);
} else {
base += l[i] - 1;
int delta = r[i] - l[i] + 1;
++cnt[delta];
int add = ((l[i] & 1) == (r[i] & 1) ? 1 : 2);
optionalSignal = min(2, optionalSignal + add);
}
}
poly.reset();
poly[0] = 1;
for (int k = 1; k <= m; ++k) {
if (2 * k <= m) cnt[2 * k] += cnt[k] / 2;
if (cnt[k] & 1) poly ^= (poly << k);
}
for (int i = 2; i <= m; ++i) poly[i] = poly[i] ^ poly[i - 2];
auto pref = [&](ll x) -> int {
ll idx = x - base;
if (idx < 0 || idx > m) return 0;
return poly[(int)idx];
};
int bad = 0;
for (int i = 0; i < n; ++i) {
if (l[i] == 0) bad ^= pref(2LL * r[i] - 2);
else bad ^= pref((ll)l[i] + r[i] - 3);
}
int totalEven;
if (optionalSignal == 0) totalEven = mandatoryParity ^ 1;
else totalEven = (optionalSignal == 1);
cout << (bad ^ totalEven) << '\n';
}
}