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.
Forget the three actual numbers for a second. If the sorted AP is , the only useful size parameter against the cap is .
Classify the move by which sorted element is increased. The largest cannot move. The smallest can only become , and the middle can only become .
Those two moves become tiny: for the smallest move, and for the middle move. So every single game has Grundy value only.
With a fake helper value , the recurrence is . The closed form is: odd gives ; otherwise strip factors of and use popcount parity.
For a whole interval of , each fixed appears in a block of length . Full blocks vanish when is even; when is odd, you only need a prefix xor of , computable from numbers .
Compressing One Game
Start with one game. Write the sorted AP as , where .
Now classify moves by which sorted element gets increased.
So every move is one of only two types:
Define
.
The initial game always has . The shift move exists when and sends to . The double move exists when and sends to .
So the whole single-game state is just one integer . Nice. The scary three-number game was wearing a fake mustache.
The Grundy Recurrence
Let be the Grundy value for a game with parameter . Then:
It is convenient to define a fake helper value . Then the recurrence becomes uniform for every :
.
That fake is never a real game. It just makes the algebra stop being annoying.
The recurrence only ever produces . The closed form is:
popcount(k) is even, and if popcount(k) is odd.Here means the exponent of in .
Why does this work? Induct on .
If is odd, then is even, is odd, and has even . Both target values are nonzero, so the mex is .
If , then has odd , so its Grundy value is . Also is an odd number whose popcount parity is opposite to the odd core of . Therefore is the opposite nonzero value from , and mex(0, opposite) gives . Multiplying by does not change the value.
If is odd, say , then the recurrence looks at and . Exactly one of those carries the zero case, and the other carries the nonzero value determined by the odd core. Passing from that odd core to flips popcount parity, so the mex with gives exactly the claimed value for .
That proves the formula.
Combining Many Games
All games are played as a disjoint sum of impartial games. Therefore Bug wins iff the xor of all Grundy values is nonzero.
For one input row, let . For a fixed cap :
.
As runs over , the same appears for a whole block of length :
.
So for one row, we xor once for every integer in the query interval. A value repeated an even number of times cancels. This gives a simple block calculation:
So we need a fast prefix xor
.
Again, is the fake helper, but all real range queries start at , so using prefix differences is fine.
Fast Prefix Xor
From the closed form, nonzero positions are exactly
.
For a fixed , all valid satisfy
, where .
For those :
Only parities of counts matter, because xor cancels pairs.
Let odd(M) be the parity of the number of integers in with odd popcount.
If , the numbers split into pairs , and each pair has exactly one odd-popcount number. So
odd(M) = (q+1) mod 2.
If 2qq2q$ has popcount parity equal to popcount(q). So
odd(M) = (q mod 2) xor (popcount(q) mod 2).
The even-popcount count parity is just (M+1 mod 2) xor odd(M).
Loop over powers of , toggle xor value if the odd-popcount count is odd, and toggle xor value if the even-popcount count is odd.
There are only about powers of up to , so each row is handled in time.
Complexity
For each series we do work. Across all test cases, the total is
,
with extra memory.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int sg(ll n) {
int v = __builtin_ctzll((unsigned long long)n);
if (v & 1) return 0;
ll odd = n >> v;
ll k = (odd - 1) / 2;
return (__builtin_popcountll((unsigned long long)k) & 1) ? 1 : 2;
}
int odd_popcount_count_parity(ll m) {
if (m & 1) {
ll q = m / 2;
return (q + 1) & 1;
}
ll q = m / 2;
return (q & 1) ^ (__builtin_popcountll((unsigned long long)q) & 1);
}
int pref_sg(ll n) {
if (n <= 0) return 0;
int ans = 0;
for (ll p = 1; p <= n; ) {
ll upto = n / p;
ll m = (upto - 1) / 2;
int odd = odd_popcount_count_parity(m);
int total = (m + 1) & 1;
int even = total ^ odd;
if (odd) ans ^= 1;
if (even) ans ^= 2;
if (p > n / 4) break;
p *= 4;
}
return ans;
}
int series_xor(ll a, ll d, ll l, ll r) {
ll L = l - a, R = r - a;
ll ql = L / d, qr = R / d;
if (ql == qr) return ((R - L + 1) & 1) ? sg(ql) : 0;
int ans = 0;
ll first_len = (ll)((__int128)(ql + 1) * d - L);
if (first_len & 1) ans ^= sg(ql);
ll last_len = R - qr * d + 1;
if (last_len & 1) ans ^= sg(qr);
if ((d & 1) && ql + 1 <= qr - 1) {
ans ^= pref_sg(qr - 1) ^ pref_sg(ql);
}
return ans;
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
int nim = 0;
while (n--) {
ll a, b, c, l, r;
cin >> a >> b >> c >> l >> r;
ll d = b - a;
nim ^= series_xor(a, d, l, r);
}
cout << (nim ? "Bug" : "Feature") << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int sg(ll n) {
int v = __builtin_ctzll((unsigned long long)n);
if (v & 1) return 0;
ll odd = n >> v;
ll k = (odd - 1) / 2;
return (__builtin_popcountll((unsigned long long)k) & 1) ? 1 : 2;
}
int odd_popcount_count_parity(ll m) {
if (m & 1) {
ll q = m / 2;
return (q + 1) & 1;
}
ll q = m / 2;
return (q & 1) ^ (__builtin_popcountll((unsigned long long)q) & 1);
}
int pref_sg(ll n) {
if (n <= 0) return 0;
int ans = 0;
for (ll p = 1; p <= n; ) {
ll upto = n / p;
ll m = (upto - 1) / 2;
int odd = odd_popcount_count_parity(m);
int total = (m + 1) & 1;
int even = total ^ odd;
if (odd) ans ^= 1;
if (even) ans ^= 2;
if (p > n / 4) break;
p *= 4;
}
return ans;
}
int series_xor(ll a, ll d, ll l, ll r) {
ll L = l - a, R = r - a;
ll ql = L / d, qr = R / d;
if (ql == qr) return ((R - L + 1) & 1) ? sg(ql) : 0;
int ans = 0;
ll first_len = (ll)((__int128)(ql + 1) * d - L);
if (first_len & 1) ans ^= sg(ql);
ll last_len = R - qr * d + 1;
if (last_len & 1) ans ^= sg(qr);
if ((d & 1) && ql + 1 <= qr - 1) {
ans ^= pref_sg(qr - 1) ^ pref_sg(ql);
}
return ans;
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
int nim = 0;
while (n--) {
ll a, b, c, l, r;
cin >> a >> b >> c >> l >> r;
ll d = b - a;
nim ^= series_xor(a, d, l, r);
}
cout << (nim ? "Bug" : "Feature") << '\n';
}
}