莫队很简单
只要找到递推式就好办,递推式:T(n+1,m)=2*T(n,m)-C(n,m)
T(n,m)=C(n,0)+C(n,1)+C(n,2)+…+C(n,m)
再根据C(n+1,m)=C(n,m)+C(n,m-1)可得到递推式
代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=100000+100;
const ll mod=1e9+7;
int R[maxn];
struct Mo{
int n,m;
int id;
}mo[maxn];
ll Ans[maxn];
ll inv[maxn];
ll fac[maxn];
ll key;
int nn,mm;
inline bool cmp(Mo a,Mo b){
return R[a.n]==R[b.n]?a.m<b.m:R[a.n]<R[b.n];
}
ll mypow(ll a,ll b){
ll sum=1;
while(b){
if(b&1) sum=sum*a%mod;
a=a*a%mod;
b>>=1;
}
return sum;
}
void init(){
fac[0]=fac[1]=1;
for(int i=2;i<maxn;i++) fac[i]=fac[i-1]*i%mod;
inv[maxn-1]=mypow(fac[maxn-1],mod-2);
for(int i=maxn-2;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
}
ll C(int a,int b){
return fac[a]*inv[b]%mod*inv[a-b]%mod;
}
void addn(){
key=(key*2%mod-C(nn,mm))%mod;
}
void deln(){
key=(key+C(nn-1,mm))%mod*inv[2]%mod;
}
void addm(){
key=(key+C(nn,mm+1))%mod;
}
void delm(){
key=(key-C(nn,mm))%mod;
}
int main(){
init();
int m;
scanf("%d",&m);
int size=sqrt(100000.0);
for(int i=1;i<=100000;i++) R[i]=i/size;
for(int i=1;i<=m;i++) scanf("%d%d",&mo[i].n,&mo[i].m),mo[i].id=i;
sort(mo+1,mo+1+m,cmp);
nn=1,mm=0;
key=1;
for(int i=1;i<=m;i++){
while(nn<mo[i].n) addn(),nn++;
while(mm<mo[i].m) addm(),mm++;
while(nn>mo[i].n) deln(),nn--;
while(mm>mo[i].m) delm(),mm--;
Ans[mo[i].id]=(key+mod)%mod;
}
for(int i=1;i<=m;i++) printf("%lld\n",Ans[i]);
}