Link
\(t\) 组询问,每组给出 \(n,k\le 10^5\),求 \(\begin{aligned}\sum\limits_{i=0}^{k}\dbinom{n}{i}\end{aligned}\),
\(t\le 10^5\)。
\(n\to n+1\) 时:
\[\begin{aligned}\sum\limits_{i=0}^{k}\dbinom{n+1}{i}&=\sum\limits_{i=0}^{k}\begin{pmatrix}\dbinom{n}{i}+\dbinom{n}{i-1}\end{pmatrix}\\&=2\sum\limits_{i=0}^{k}\dbinom{n}{i}-\dbinom{n}{k}\end{aligned} \]移项反解得 \(n\to n-1\) 时:
\[\begin{aligned}\sum\limits_{i=0}^{k}\dbinom{n-1}{i}=\dfrac{\sum\limits_{i=0}^{k}\dbinom{n}{i}+\dbinom{n}{k}}{2}\end{aligned} \]\(k\to k+1\) 时:
\[\begin{aligned}\sum\limits_{i=0}^{k+1}\dbinom{n}{i}=\sum\limits_{i=0}^{k}\dbinom{n}{i}+\dbinom{n}{k+1}\end{aligned} \]同理,\(k\to k-1\) 时:
\[\begin{aligned}\sum\limits_{i=0}^{k-1}\dbinom{n}{i}=\sum\limits_{i=0}^{k}\dbinom{n}{i}-\dbinom{n}{k+1}\end{aligned} \]注意到上面四个转移式的余项都为单个组合数,而预处理阶乘及逆元计算组合数时 \(O(1)\) 的,所以上述四个转移也是 \(O(1)\) 的。
莫队即可,复杂度 \(O(n\sqrt n)\)。
#include <bits/stdc++.h> #define int long long namespace mystd { inline int read() { char c = getchar(); int x = 0, f = 1; while (c < '0' || c > '9') f = (c == '-') ? -1 : f, c = getchar(); while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0', c = getchar(); return x * f; } inline void write(int x) { if (x < 0) x = ~(x - 1), putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } } using namespace std; using namespace mystd; const int maxn = 2e5 + 200;// 不知道为啥要开大的空间,不然就过不去样例 const int mod = 1e9 + 7; int n, l, r, b, c, mx, ans[maxn], fac[maxn], inv[maxn], ifac[maxn]; struct qry { int l, r, id; bool operator < (const qry &rhs) const { return l / b == rhs.l / b ? r < rhs.r : l < rhs.l; } } q[maxn]; int C(int n, int m) { return fac[n] * ifac[m] % mod * ifac[n - m] % mod; } void addr() { c = ((c * 2 % mod - C(r++, l)) % mod + mod) % mod; } void delr() { c = inv[2] * ((c + C(--r, l)) % mod) % mod; } void addl() { c = ((c - C(r, l--)) % mod + mod) % mod; } void dell() { c = (c + C(r, ++l)) % mod; } signed main() { n = read(), b = sqrt(n); for (int i = 1; i <= n; i++) { q[i] = (qry) { read(), read(), i }; swap(q[i].l, q[i].r); mx = max(mx, q[i].r); } sort(q + 1, q + n + 1); r = 1, c = 1; fac[0] = inv[1] = ifac[0] = 1; for (int i = 1; i <= mx; i++) { if (i >= 2) inv[i] = (mod - mod / i) * inv[mod % i] % mod; fac[i] = fac[i - 1] * i % mod; ifac[i] = ifac[i - 1] * inv[i] % mod; } for (int i = 1; i <= n; i++) { while (l > q[i].l) addl(); while (l < q[i].l) dell(); while (r < q[i].r) addr(); while (r > q[i].r) delr(); ans[q[i].id] = c; } for (int i = 1; i <= n; i++) write(ans[i]), puts(""); return 0; }