题意
给你n个苹果,求从中取出最多m个苹果的方案数。
题解
根据题面,也就是求
S(n,m)=ΣC(n,i)(0<=i<=m)
S
(
n
,
m
)
=
Σ
C
(
n
,
i
)
(
0
<=
i
<=
m
)
。
可以简单推出S(n,m)=S(n,m-1)+C(n,m),S(n,m)=2*S(n-1,m)-C(n-1,m),这样就可以用莫队了,转移时O(1)的,总复杂度为O(T*sqrt(maxn))
AC代码
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#define N 100005
#define mod 1000000007
using namespace std;
typedef long long ll;
ll a[N],pos[N],f[N],inv[N],len;
struct node
{
ll l,r,id;
node(){}
node(ll l,ll r,ll id)
{
this->l=r;
this->r=r;
this->id=id;
}
}q[N];
ll ansa[N];
bool cmp(node a,node b)
{
return pos[a.l]<pos[b.l]||pos[a.l]==pos[b.l]&&a.r<b.r;
}
ll qmi(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b%2)ans=ans*a%mod;
a=a*a%mod;
b/=2;
}
return ans;
}
ll C(ll n,ll m)
{
return f[n]*inv[m]%mod*inv[n-m]%mod;
}
int main()
{
ll n=100000,m,INV=(mod+1)/2;
f[0]=1;
for(ll i=1;i<=n;i++)
f[i]=(f[i-1]*i)%mod;
for(ll i=0;i<=n;i++)
inv[i]=qmi(f[i],mod-2);
scanf("%lld",&m);
len=(ll)sqrt((double)n+0.1);
for(ll i=1;i<=n;i++)
pos[i]=(i-1)/len+1;
for(ll i=0;i<m;i++)
{
scanf("%lld%lld",&q[i].r,&q[i].l);
q[i].id=i;
}
sort(q,q+m,cmp);
ll ans=1;
ll l=0,r=1;
for(ll i=0;i<m;i++)
{
if(r<q[i].r)
{
for(;r<q[i].r;r++)
ans=(2*ans-C(r,l)+mod)%mod;
}
if(q[i].l<l)
{
for(;l>q[i].l;l--)
ans=(ans-C(r,l)+mod)%mod;
}
if(r>q[i].r)
{
for(r=r-1;r>=q[i].r;r--)
ans=(ans+C(r,l))*INV%mod;
r++;
}
if(q[i].l>l)
{
for(l=l+1;l<=q[i].l;l++)
ans=(ans+C(r,l))%mod;
l--;
}
ansa[q[i].id]=ans;
}
for(ll i=0;i<m;i++)
printf("%lld\n",ansa[i]);
}