题意:
T次询问,每次给出n,m。求sigma(k:0->m)C(n, k)。
题解:
用离线莫队来做。
令S(n,m) = sigma(k:0->m)C(n, k)。
S(n+1, m) = 2S(n, m) - C(n, m) S(n-1, m) = (S(n, m) + C(n-1, m)) / 2
S(n, m+1) = S(n, m) + C(n, m+1) S(n, m-1) = S(n, m) - C(n, m)
#include <bits/stdc++.h> using namespace std; const int mod = 1e9+7; const int N = 1e5+10; int t; int blk; int blg[N]; int fac[N], inv[N], tmp[N]; int l, r, now; int ans[N]; struct ask { int l, r, id; bool operator < (const ask &a) { return blg[l] == blg[a.l] ? r < a.r : l < a.l; } }q[N]; int C(int n, int m) { int res = 1ll*fac[n]*inv[m]%mod; res = 1ll*res*inv[n-m]%mod; return res; } void update(int k, int t) { if(t == 1) { if(~k) now = (2ll*now-C(l, r)+mod)%mod; else now = 1ll*(now+C(l-1, r))*tmp[2]%mod; } else { if(~k) now = (now+C(l, r))%mod; else now = (now-C(l, r)+mod)%mod; } } int main() { fac[0] = fac[1] = tmp[1] = inv[0] = inv[1] = 1; for(int i = 2; i < N; i++) { fac[i] = 1ll*fac[i-1]*i%mod; tmp[i] = 1ll*(mod-mod/i)*tmp[mod%i]%mod; inv[i] = 1ll*inv[i-1]*tmp[i]%mod; } scanf("%d", &t); int up = 0; for(int i = 1; i <= t; i++) { scanf("%d%d", &q[i].l, &q[i].r); up = max(up, q[i].r); q[i].id = i; } blk = sqrt(t); for(int i = 1; i <= up; i++) blg[i] = (i-1)/blk; sort(q+1, q+t+1); now = 1; l = 0, r = 0; for(int i = 1; i <= t; i++) { while(r > q[i].r) update(-1, 0), r--; while(l < q[i].l) update(1, 1), l++; while(l > q[i].l) update(-1, 1), l--; while(r < q[i].r) r++, update(1, 0); ans[q[i].id] = now; } for(int i = 1; i <= t; i++) printf("%d ", ans[i]); }