AT_tenka1_2014_final_d 高橋君
给定若干个 \(n,m\),求 \(\sum\limits_{i=0}^{m} \dbinom{n}{i}\)。为方便,记 \(C(n,m)=\dbinom{n}{m},S(n,m)=\sum\limits_{i=0}^{m} C(n,i)\)。
我们知道 \(C(n,m)=C(n-1,m-1)+C(n-1,m)\),那么:
\[S(n,m)=C(n-1,0)+\sum\limits_{i=1}^{m} C(n-1,i-1)+C(n-1,i)=2S(n-1,m)-C(n-1,m)
\]
变形得到:
\[S(n-1,m)=\dfrac{S(n,m)+C(n-1,m)}{2}
\]
\[S(n+1,m)=2S(n,m)-C(n,m)
\]
同时又有:
\[S(n,m-1)=S(n,m)-C(n,m)
\]
\[S(n,m+1)=S(n,m)+C(n,m+1)
\]
所以发现 \(n,m\) 可以 \(O(1)\) 加减 \(1\),用莫队维护,初始时 \(S(0,0)=1\),时间复杂度 \(O(W\sqrt q)\),\(W\) 为值域,最大为 \(10^5\)。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
const int MAXN=1e5+10,MOD=1e9+7;
int t,N,len,bel[MAXN],ANS[MAXN];
long long P[MAXN],inv[MAXN],ans=1;
struct node{int n,m,pos;}p[MAXN];
inline bool cmp(node x,node y)
{
if(bel[x.n]!=bel[y.n]) return x.n<y.n;
return (bel[x.n]&1)?x.m<y.m:x.m>y.m;
}
inline long long C(int n,int m)
{
if(n<m) return 0;
return P[n]*inv[m]%MOD*inv[n-m]%MOD;
}
inline long long ksm(long long a,int b)
{
long long ans=1;
while(b)
{
if(b&1) ans=ans*a%MOD;
a=a*a%MOD,b>>=1;
}
return ans;
}
int main()
{
#ifdef ONLINE_JUDGE
cin.tie(0),cout.tie(0);
ios::sync_with_stdio(0);
#endif
cin>>t;
for(register int i=1;i<=t;++i)
{
cin>>p[i].n>>p[i].m;
N=max(N,p[i].n);p[i].pos=i;
}
len=N/sqrt(t);
for(register int i=1;i<=N;++i) bel[i]=(i-1)/len+1;
sort(p+1,p+t+1,cmp);
P[0]=1;for(register int i=1;i<=N;++i) P[i]=P[i-1]*i%MOD;
inv[N]=ksm(P[N],MOD-2);for(register int i=N-1;i>=0;--i) inv[i]=inv[i+1]*(i+1)%MOD;
for(register int i=1,n=0,m=0;i<=t;++i)
{
while(n<p[i].n) ans=(ans*2-C(n,m))%MOD,++n;
while(m>p[i].m) ans=(ans-C(n,m))%MOD,--m;
while(n>p[i].n) ans=(ans+C(n-1,m))%MOD*500000004%MOD,--n;
while(m<p[i].m) ans=(ans+C(n,m+1))%MOD,++m;
ans=(ans+MOD)%MOD;ANS[p[i].pos]=ans;
}
for(register int i=1;i<=t;++i) cout<<ANS[i]<<'\n';
return 0;
}

浙公网安备 33010602011771号