[机房测试]cook(多次询问组合数前缀和的求法)

题面:

漂亮国的大厨扑擅长做菜,但是由于严重的通货膨胀,他必须规划一下自己的买菜计划。
有个排成一排的摊位,编号为,第个摊位售卖一种价格为的食材
在一天中,每天会发生以下两种事件之一:

  1. 摊位涨价:编号在的摊位涨价了x块钱
  2. 大厨买菜: 扑准备在这些摊位上,买价格不超过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;
	}
posted @ 2021-11-08 21:33  Smallbasic  阅读(96)  评论(0)    收藏  举报