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.
Sort-selected-by-strength sounds scary, but because all strengths are powers of two, each selected reindeer either contributes exactly one power of two or contributes . No carries. That is the first crack in the wall.
If the selected exponents after sorting are , the -th chosen reindeer contributes when . Notice that the exponents are strictly decreasing, so the carrying capacity is literally a bitmask.
For a fixed capacity value with set bits , the positive-contributing reindeer are forced: the -th one must have exponent . Extra selected reindeer may only be a zero-contributing tail, and that tail can use only exponents .
To count capacities , scan bits from high to low. When has a at bit , branch by putting there in the capacity. If higher bits were already fixed to , then lower arbitrary choices can only use exponents at most , so they contribute a clean factor .
While following the prefix equal to , setting bit to requires choosing one reindeer of exponent . Keep how many times each exponent was already required, and multiply by modulo . Then answer is .
The Bitmask Hiding In Plain Sight
Suppose we choose some reindeer and sort their exponents in non-increasing order:
The actual strengths are , so the -th selected reindeer contributes
That is either
if , or otherwise.
Now the important part:
So the positive contribution exponents
are strictly decreasing. Therefore the carrying capacity has no repeated powers of two and no carries. It is just a binary mask. Very cute. Also very easy to miss, because the statement is doing its best to look like a tax form.
Exact Capacity Shape
Say a positive capacity has set bits
If these are the positive contributions, then the -th positive-contributing reindeer must have exponent
So the required exponents are forced.
After these positive contributors, any extra selected reindeer must contribute . The next selected reindeer would be in position , so it contributes positively iff its exponent is at least . Therefore zero-tail reindeer can only have exponent .
This gives an exact counting formula, but summing it over all capacities is impossible directly. There are way too many masks. We need to count all capacities below by binary prefix logic.
Counting Capacities Less Than
We compute the number of selected subsets whose carrying capacity is , then subtract from all subsets.
Scan bits from down to . Bit is enough because strengths are at most , so the highest possible contribution bit is .
Maintain:
ways: the number of ways to choose the forced reindeer for that equal prefix;used[e]: how many forced reindeer of exponent the current prefix already needs.Now suppose we are at bit and the higher bits are still equal to .
If , then capacities smaller than can be formed by setting this capacity bit to and making all lower bits arbitrary.
Since higher positive bits were already chosen, a reindeer that would create bit must have exponent
If we set bit to , then all future positive contributions must use exponents at most . And once we are already smaller than , lower bits do not matter anymore. So every remaining reindeer with exponent may be chosen or not chosen freely.
That contributes
where is the number of current reindeer with exponent at most .
Then, to keep matching , since , we must force bit to be . That means choosing one more reindeer of exponent .
If we already used reindeer of this exponent in the forced prefix, the binomial factor changes from
to
So multiply by
Modulo , division means multiplying by modular inverse. Since , we can precompute these tiny inverses. If or , the prefix becomes impossible and ways becomes .
If , we do not add anything; we simply keep matching the prefix with bit .
At the end, the accumulated value is exactly the number of subsets with carrying capacity .
Why The Free Lower Choices Work
This is the part worth double-checking, because otherwise the solution feels like black magic.
When the prefix has already selected positive contributors and we skip bit , exponent is forbidden. Any later positive contributor is placed after those contributors, so to create a lower bit it must have exponent at most
Any selected reindeer with exponent at most that will only affect lower bits or contribute . Since we are already below , all such choices are valid. So they really do give a factor of .
The forced prefix uses only exponents at least , so there is no overlap with those free lower choices. Nice and clean.
Updates
We only store cnt[0..60] and the total number of reindeer .
For add/remove queries, update one count and .
For type 3 x:
pref[i]=cnt[0]+...+cnt[i].less be the number of subsets with capacity .
The empty subset has capacity , and since every query has , subtracting all subsets with capacity automatically removes it. No awkward special case. We love when the math cleans up after itself.
Complexity
Each query scans only bits and touches arrays of size .
So the complexity is
per query, with memory besides precomputed powers and inverses. That is easily fine for queries.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const int MAXC = 60;
const int MOD = 998244353;
const int MAXN = 600000 + 5;
ll modpow(ll a, ll e) {
ll r = 1;
while (e) {
if (e & 1) r = r * a % MOD;
a = a * a % MOD;
e >>= 1;
}
return r;
}
int main() {
setIO();
int n, m;
cin >> n >> m;
array<int, MAXC + 1> cnt{};
for (int i = 0; i < n; i++) {
int c;
cin >> c;
cnt[c]++;
}
vector<int> pow2(MAXN), inv(70);
pow2[0] = 1;
for (int i = 1; i < MAXN; i++) pow2[i] = pow2[i - 1] * 2LL % MOD;
for (int i = 1; i < 70; i++) inv[i] = modpow(i, MOD - 2);
int total = n;
while (m--) {
int type;
ll x;
cin >> type >> x;
if (type == 1) {
cnt[(int)x]++;
total++;
} else if (type == 2) {
cnt[(int)x]--;
total--;
} else {
array<int, MAXC + 1> pref{}, used{};
pref[0] = cnt[0];
for (int i = 1; i <= MAXC; i++) pref[i] = pref[i - 1] + cnt[i];
ll less = 0;
ll ways = 1;
int h = 0;
for (int p = MAXC; p >= 0; p--) {
if (((x >> p) & 1LL) == 0) continue;
int e = p + h;
if (ways) {
int low = min(e - 1, MAXC);
less = (less + ways * (low >= 0 ? pow2[pref[low]] : 1)) % MOD;
}
if (e > MAXC || used[e] >= cnt[e]) {
ways = 0;
} else if (ways) {
ways = ways * (cnt[e] - used[e]) % MOD * inv[used[e] + 1] % MOD;
}
if (e <= MAXC) used[e]++;
h++;
}
ll ans = (pow2[total] - less) % MOD;
if (ans < 0) ans += MOD;
cout << ans << '\n';
}
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const int MAXC = 60;
const int MOD = 998244353;
const int MAXN = 600000 + 5;
ll modpow(ll a, ll e) {
ll r = 1;
while (e) {
if (e & 1) r = r * a % MOD;
a = a * a % MOD;
e >>= 1;
}
return r;
}
int main() {
setIO();
int n, m;
cin >> n >> m;
array<int, MAXC + 1> cnt{};
for (int i = 0; i < n; i++) {
int c;
cin >> c;
cnt[c]++;
}
vector<int> pow2(MAXN), inv(70);
pow2[0] = 1;
for (int i = 1; i < MAXN; i++) pow2[i] = pow2[i - 1] * 2LL % MOD;
for (int i = 1; i < 70; i++) inv[i] = modpow(i, MOD - 2);
int total = n;
while (m--) {
int type;
ll x;
cin >> type >> x;
if (type == 1) {
cnt[(int)x]++;
total++;
} else if (type == 2) {
cnt[(int)x]--;
total--;
} else {
array<int, MAXC + 1> pref{}, used{};
pref[0] = cnt[0];
for (int i = 1; i <= MAXC; i++) pref[i] = pref[i - 1] + cnt[i];
ll less = 0;
ll ways = 1;
int h = 0;
for (int p = MAXC; p >= 0; p--) {
if (((x >> p) & 1LL) == 0) continue;
int e = p + h;
if (ways) {
int low = min(e - 1, MAXC);
less = (less + ways * (low >= 0 ? pow2[pref[low]] : 1)) % MOD;
}
if (e > MAXC || used[e] >= cnt[e]) {
ways = 0;
} else if (ways) {
ways = ways * (cnt[e] - used[e]) % MOD * inv[used[e] + 1] % MOD;
}
if (e <= MAXC) used[e]++;
h++;
}
ll ans = (pow2[total] - less) % MOD;
if (ans < 0) ans += MOD;
cout << ans << '\n';
}
}
return 0;
}