[机房测试]cook(多次询问组合数前缀和的求法)
题面:
漂亮国的大厨扑擅长做菜,但是由于严重的通货膨胀,他必须规划一下自己的买菜计划。
有个排成一排的摊位,编号为,第个摊位售卖一种价格为的食材
在一天中,每天会发生以下两种事件之一:
- 摊位涨价:编号在的摊位涨价了x块钱
- 大厨买菜: 扑准备在这些摊位上,买价格不超过x块钱的食材不超过y个,ta问你有多少种方案。
Sol:
显然加法和个数可以简单分块维护,询问本质上是个组合数前缀和,离线下来有莫队的经典求法。
我们设:
\[S(n,m)=\sum_{i=0}^m \binom{n}{i}
\]
则对于 \(n\), \(m\) 的移动,显然有:
\[S(n,m + 1)=S(n,m)+\binom{n}{m+1}
\]
\[S(n,m - 1)=S(n,m)-\binom{n}{m}
\]
\[S(n + 1,m)=2S(n,m)-\binom{n}{m}
\]
\[S(n - 1,m)={S(n,m)+\binom{n-1}{m}\over 2}
\]
直接套莫队即可。
int res = 1, l = 0, r = 0;
for (int i = 1; i <= top; ++i) {
while (r < q[i].r) {
res = res + res; if (res >= mod) res -= mod;
res = res - C(r, l); if (res < 0) res += mod; ++r;
}
while (r > q[i].r) {
res = res + C(r - 1, l);
if (res >= mod) res -= mod;
res = (1ll * res * hf) % mod;
--r;
}
while (l > q[i].l) {
res = res - C(r, l); if (res < 0) res += mod; --l;
}
while (l < q[i].l) {
++l; res = res + C(r, l); if (res >= mod) res -= mod;
}
ans[q[i].id] = res;
}

浙公网安备 33010602011771号