莫队很简单
只要找到递推式就好办,递推式: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]);
}