题目:求C(n,0)+C(n,1)+C(n,2)+.......+C(n,m)
思路:S(l,r)=S(l,r-1)+C(l,r) S(l,r)=2*S(l-1,r)-C(l-1,r);(想想杨辉三角就容易看出来了)
S(l,r)=S(l,r+1)-C(l,r+1) S(l,r)=(S(l+1,r)-C(l,r))/2; (由上面得到)
预处理阶乘逆元,然后莫队搞一下。
不告诉你(l,r)你就不知道当作区间的题来做???思维定式了要。。我好菜。。。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int N=1e5;
const ll mod=1e9+7;
ll fac[maxn],inv[maxn];
ll qmod(ll x,ll p)
{
ll ans=1;
while(p)
{
if(p&1) ans=ans*x%mod;
x=x*x%mod;
p>>=1ll;
}
return ans;
}
void init()
{
fac[0]=1ll;
for(int i=1;i<=N;i++)
fac[i]=1ll*i*fac[i-1]%mod;
inv[N]=qmod(fac[N],mod-2);
for(int i=N-1;i>=0;i--)
inv[i]=1ll*(i+1)*inv[i+1]%mod;
}
ll C(int n,int m)
{
if(m>n) return 0ll;
return fac[n]*inv[n-m]%mod*inv[m]%mod;
}
struct node{
int l,r,id;
}s[maxn];
int n,block[maxn],T;
ll ans[maxn];
bool cmp(const node &a,const node &b)
{
if(block[a.l]==block[b.l]) return a.r<b.r;
return block[a.l]<block[b.l];
}
int main()
{
init();
ll _2=qmod(2ll,mod-2ll);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&s[i].l,&s[i].r);
s[i].id=i;
}
int t=(int)sqrt(1.0*n);
for(int i=0;i<=n;i++)
block[i]=i/t;
sort(s+1,s+n+1,cmp);
int l=1,r=0;
ll sum=1ll;
for(int i=1;i<=n;i++)
{
while(r<s[i].r)
{
r++;
sum=(sum+C(l,r))%mod;
}
while(r>s[i].r)
{
sum=(sum-C(l,r)+mod)%mod;
r--;
}
while(l<s[i].l)
{
sum=(2ll*sum%mod-C(l,r)+mod)%mod;
l++;
}
while(l>s[i].l)
{
l--;
sum=(sum+C(l,r))%mod*_2%mod;
}
ans[s[i].id]=sum;
}
for(int i=1;i<=n;i++)
printf("%lld\n",ans[i]);
return 0;
}