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 updates and multiple queries — easy version is just one static subarray. First ask: after fixing all non- values, how much total mass is left for the wildcards?
Let the subarray contain wildcards and let their remaining sum be . If , you're dead: no valid sequence. Otherwise every filling is just a composition of into non-negative parts.
For a position , split its prefix sum into two parts:
where is the sum of fixed values up to , and is the sum of wildcard variables up to .
If wildcards appear up to position , then is the sum of the first variables in a uniformly chosen composition of into parts. You only need three aggregated sums over positions:
The number of compositions is
For sum of first parts:
and
Plug this into and sum over all positions.
We need compute for one subarray .
Let:
If , there are no valid sequences, so the answer is .
If , there is only one possible sequence. It is valid iff , and the answer is just
Now assume .
Each valid sequence corresponds exactly to a composition
The number of such compositions is
Classic stars and bars. No magic, no goblins.
For every position in the subarray, define:
Then the actual prefix sum at position is
So the contribution of position over all valid fillings is
Expand the square:
So we only need the first two moments of , where is the sum of the first parts in a uniformly chosen composition of into parts.
For , the number of compositions with that value is
with the natural edge cases. This is the beta-binomial distribution with parameters .
The useful formulas are:
and
The first one is also obvious by symmetry: total mass is shared equally among variables on average.
The second one is variance plus mean squared:
All division is modulo . Since , denominators are invertible. Nice.
For every position, we need and . While scanning the subarray once, compute:
Now sum the expanded formula over all positions.
The answer is:
And
So everything is determined by those four simple aggregates. Beautifully unfair for anyone trying DP.
For each test case, we scan the queried subarray a constant number of times. Since and the sum of over test cases is bounded,
time is enough, mainly for factorial precomputation and array scanning.
Memory usage is
for factorials and inverse factorials.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const ll MOD = 998244353;
const int MAXF = 1300005; // max m + max n + a little safety
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;
}
vector<ll> fact, ifact;
ll C(int n, int r) {
if (r < 0 || r > n || n < 0) return 0;
return fact[n] * ifact[r] % MOD * ifact[n - r] % MOD;
}
int main() {
setIO();
fact.assign(MAXF, 1);
ifact.assign(MAXF, 1);
for (int i = 1; i < MAXF; i++) fact[i] = fact[i - 1] * i % MOD;
ifact[MAXF - 1] = modpow(fact[MAXF - 1], MOD - 2);
for (int i = MAXF - 2; i >= 0; i--) ifact[i] = ifact[i + 1] * (i + 1) % MOD;
int TC;
cin >> TC;
while (TC--) {
int n, q;
cin >> n >> q;
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
while (q--) {
int op, l, r;
ll m;
cin >> op >> l >> r >> m;
ll fixedSum = 0;
int k = 0;
for (int i = l; i <= r; i++) {
if (a[i] == -1) k++;
else fixedSum += a[i];
}
if (fixedSum > m) {
cout << 0 << '\n';
continue;
}
ll M = m - fixedSum;
if (k == 0) {
if (M != 0) {
cout << 0 << '\n';
continue;
}
ll pref = 0, ans = 0;
for (int i = l; i <= r; i++) {
pref = (pref + a[i]) % MOD;
ans = (ans + pref * pref) % MOD;
}
cout << ans << '\n';
continue;
}
ll N = C((int)(M + k - 1), k - 1);
ll prefFixed = 0;
int wildSeen = 0;
ll A0 = 0; // sum F_i^2
ll A1 = 0; // sum F_i * t_i
ll T1 = 0; // sum t_i
ll T2 = 0; // sum t_i^2
for (int i = l; i <= r; i++) {
if (a[i] == -1) {
wildSeen++;
} else {
prefFixed += a[i];
}
ll F = prefFixed % MOD;
ll T = wildSeen % MOD;
A0 = (A0 + F * F) % MOD;
A1 = (A1 + F * T) % MOD;
T1 = (T1 + T) % MOD;
T2 = (T2 + T * T) % MOD;
}
ll kMod = k % MOD;
ll MMod = M % MOD;
ll invK = modpow(kMod, MOD - 2);
ll invK2 = invK * invK % MOD;
ll invK1 = modpow((k + 1) % MOD, MOD - 2);
ll ans = 0;
// N * sum F_i^2
ans = (ans + N * A0) % MOD;
// 2 * (N * M / k) * sum F_i t_i
ll linearCoeff = N * MMod % MOD * invK % MOD;
ans = (ans + 2 * linearCoeff % MOD * A1) % MOD;
// N * [ M(M+k)/(k^2(k+1)) * sum t_i(k-t_i)
// + M^2/k^2 * sum t_i^2 ]
ll sumTkMinusT2 = (kMod * T1 % MOD - T2 + MOD) % MOD;
ll coefVar = MMod * ((M + k) % MOD) % MOD;
coefVar = coefVar * invK2 % MOD * invK1 % MOD;
ll coefMeanSq = MMod * MMod % MOD * invK2 % MOD;
ll secondMomentPart = (coefVar * sumTkMinusT2 + coefMeanSq * T2) % MOD;
ans = (ans + N * secondMomentPart) % MOD;
cout << ans % MOD << '\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 ll MOD = 998244353;
const int MAXF = 1300005; // max m + max n + a little safety
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;
}
vector<ll> fact, ifact;
ll C(int n, int r) {
if (r < 0 || r > n || n < 0) return 0;
return fact[n] * ifact[r] % MOD * ifact[n - r] % MOD;
}
int main() {
setIO();
fact.assign(MAXF, 1);
ifact.assign(MAXF, 1);
for (int i = 1; i < MAXF; i++) fact[i] = fact[i - 1] * i % MOD;
ifact[MAXF - 1] = modpow(fact[MAXF - 1], MOD - 2);
for (int i = MAXF - 2; i >= 0; i--) ifact[i] = ifact[i + 1] * (i + 1) % MOD;
int TC;
cin >> TC;
while (TC--) {
int n, q;
cin >> n >> q;
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
while (q--) {
int op, l, r;
ll m;
cin >> op >> l >> r >> m;
ll fixedSum = 0;
int k = 0;
for (int i = l; i <= r; i++) {
if (a[i] == -1) k++;
else fixedSum += a[i];
}
if (fixedSum > m) {
cout << 0 << '\n';
continue;
}
ll M = m - fixedSum;
if (k == 0) {
if (M != 0) {
cout << 0 << '\n';
continue;
}
ll pref = 0, ans = 0;
for (int i = l; i <= r; i++) {
pref = (pref + a[i]) % MOD;
ans = (ans + pref * pref) % MOD;
}
cout << ans << '\n';
continue;
}
ll N = C((int)(M + k - 1), k - 1);
ll prefFixed = 0;
int wildSeen = 0;
ll A0 = 0; // sum F_i^2
ll A1 = 0; // sum F_i * t_i
ll T1 = 0; // sum t_i
ll T2 = 0; // sum t_i^2
for (int i = l; i <= r; i++) {
if (a[i] == -1) {
wildSeen++;
} else {
prefFixed += a[i];
}
ll F = prefFixed % MOD;
ll T = wildSeen % MOD;
A0 = (A0 + F * F) % MOD;
A1 = (A1 + F * T) % MOD;
T1 = (T1 + T) % MOD;
T2 = (T2 + T * T) % MOD;
}
ll kMod = k % MOD;
ll MMod = M % MOD;
ll invK = modpow(kMod, MOD - 2);
ll invK2 = invK * invK % MOD;
ll invK1 = modpow((k + 1) % MOD, MOD - 2);
ll ans = 0;
// N * sum F_i^2
ans = (ans + N * A0) % MOD;
// 2 * (N * M / k) * sum F_i t_i
ll linearCoeff = N * MMod % MOD * invK % MOD;
ans = (ans + 2 * linearCoeff % MOD * A1) % MOD;
// N * [ M(M+k)/(k^2(k+1)) * sum t_i(k-t_i)
// + M^2/k^2 * sum t_i^2 ]
ll sumTkMinusT2 = (kMod * T1 % MOD - T2 + MOD) % MOD;
ll coefVar = MMod * ((M + k) % MOD) % MOD;
coefVar = coefVar * invK2 % MOD * invK1 % MOD;
ll coefMeanSq = MMod * MMod % MOD * invK2 % MOD;
ll secondMomentPart = (coefVar * sumTkMinusT2 + coefMeanSq * T2) % MOD;
ans = (ans + N * secondMomentPart) % MOD;
cout << ans % MOD << '\n';
}
}
return 0;
}