热身训练1 Problem B. Harvest of Apples
http://acm.hdu.edu.cn/showproblem.php?pid=6333
题意: 求 C(0,n)+C(1,n)+...+C(m,n)
分析:
这道题,我们令s(m,n) = C(0,n)+C(1,n)+...+C(m,n)
那么这道题就变成求各种s(m, n)
于是,莫队这个算法便可浮现在脑海里!
我们现在需要用O(1)的时间转移式子
s(m,n)=s(m-1,n)+C(m,n)
s(m,n)=s(m+1,n)-C(m+1,n)
S(m,n)=2*s(m,n-1)-C(m,n-1) ps:这个推导的方法,可以从“杨辉三角”中,轻松看出
S(m,n)=(s(m,n+1)+C(m,n))/2
ok,这道题AC了
接下来便是莫队板子了!
#include<bits/stdc++.h>
using namespace std;
#define re register int #define LL long long #define int long long const int N=1e5+5; const LL mo=1e9+7; int blo[N]; LL fac[N], inv[N], iv[N]; struct node{int a, b, id;}ask[N]; bool cmp(const node&x, const node&y) { if(blo[x.a] == blo[y.a]) return x.b < y.b; return blo[x.a] < blo[y.a]; } inline void init() { fac[0] = fac[1] = iv[1] = inv[1] = inv[0] = 1ll; for(re i=2, sq=sqrt(100000);i<=100000;++i) { iv[i] = mo - mo / i * iv[mo%i] % mo; inv[i] = inv[i-1] * iv[i] % mo; fac[i] = fac[i-1] * i % mo; blo[i] = (i-1) / sq + 1; } } inline LL getc(const int x, const int y) { if(x > y) return 0; return fac[y] * inv[x] % mo * inv[y-x] % mo; } int lt, rt; LL Tot; inline void Del1()
{ Tot = ((Tot - getc(lt, rt)) % mo + mo) % mo; lt --; } inline void Add1() { lt ++; Tot = ((Tot + getc(lt, rt)) % mo + mo) % mo; } inline void Del2() { rt --; Tot = ((Tot + getc(lt, rt)) % mo * iv[2]) % mo; } inline void Add2() { Tot = ((2 * Tot % mo - getc(lt, rt)) % mo + mo) % mo; rt ++; } LL ans[N]; signed main() { init(); int m; scanf("%lld",&m); for(re i=1;i<=m;++i) { scanf("%lld%lld",&ask[i].b,&ask[i].a); ask[i].id = i; } sort(ask+1, ask+1+m, cmp); lt=0; rt=0; Tot=1; for(re i=1;i<=m;++i) { while(rt < ask[i].b) Add2(); while(lt > ask[i].a) Del1(); while(rt > ask[i].b) Del2(); while(lt < ask[i].a) Add1(); ans[ask[i].id] = Tot; } for(re i=1;i<=m;++i) printf("%lld\n", ans[i]); }