HDU6333 Problem B. Harvest of Apples
莫队算法 求(0,n)~(m,n)组合数之和
#include <bits/stdc++.h>
using namespace std;
const int MAX=1e5+5;
const int BLOCK=(int)sqrt(1e5);
const long long MOD=1e9+7;
long long fact[MAX],inv[MAX];
struct ask
{
int n,m,id,block;
long long ans;
}a[MAX];
bool cmp1(ask b,ask c)
{
return b.block==c.block?b.m<c.m:b.block<c.block;
}
bool cmp2(ask b,ask c)
{
return b.id<c.id;
}
long long inv_(long long a,long long m)
{
if(a==1) return 1;
return inv_(m%a,m)*(m-m/a)%m;
}
void init()
{
fact[0]=1;inv[0]=1;
for(int i=1;i<MAX;i++)
{
fact[i]=(fact[i-1]*i)%MOD;
inv[i]=inv_(fact[i],MOD);
}
}
int main()
{
int t;
init();
scanf("%d",&t);
for(int k=0;k<t;k++)
{
scanf("%d%d",&a[k].n,&a[k].m);
a[k].id=k;
a[k].block=a[k].n/BLOCK;
}
sort(a,a+t,cmp1);
long long sum=1;
for(int i=1,k=a[0].n;i<=a[0].m;i++)
sum+=fact[k]*inv[i]%MOD*inv[k-i]%MOD;
a[0].ans=sum;
int l=a[0].n,r=a[0].m,L,R;
for(int i=1;i<t;i++)
{
L=a[i].n,R=a[i].m;
while(L>l)
{
sum=(2*sum-fact[l]*inv[r]%MOD*inv[l-r]%MOD+MOD)%MOD;
l++;
}
while(L<l)
{
sum=(sum+fact[l-1]*inv[r]%MOD*inv[l-1-r]%MOD)%MOD*inv[2]%MOD;
l--;
}
while(R>r)
{
sum=(sum+fact[l]*inv[r+1]%MOD*inv[l-r-1]%MOD)%MOD;
r++;
}
while(R<r)
{
sum=(sum-fact[l]*inv[r]%MOD*inv[l-r]%MOD+MOD)%MOD;
r--;
}
a[i].ans=sum;
}
sort(a,a+t,cmp2);
for(int i=0;i<t;i++) printf("%I64d\n",a[i].ans);
return 0;
}
/*
S(n,m)=S(n,m-1)+(n,m)
S(n,m)=2S(n-1,m)-(n-1,m)
(n,m)=m==0?1:n!/m!/(n-m)!
*/