题目
t(t<=1e5)组询问,
每次给出n,m(1<=m<=n<=1e5),求
思路来源
HDU 6333 Harvest of Apples [ 莫队算法 ]_Originum的博客-CSDN博客
题解
n=2e5是的极限,所以1e5还是可以莽一莽离线莫队,主要是O(1)转移
用的万能公式,具体数学里多次提到
记,可以发现,
,只需对上式,以n-1代n,变形一下就搞出来了
,注意/2用*inv2
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int inv2=(mod+1)/2;
const int maxn=1e5;
const int N=maxn+5;
ll Finv[N],jc[N];
ll modpow(ll x,ll n,ll mod)
{
ll res=1;
for(;n;x=x*x%mod,n/=2)
if(n&1)res=res*x%mod;
return res;
}
void init()
{
jc[0]=Finv[0]=1;
for(int i=1;i<=maxn;++i)
{
jc[i]=jc[i-1]*i;
if(jc[i]>=mod)jc[i]%=mod;
}
Finv[maxn]=modpow(jc[maxn],mod-2,mod);
for(int i=maxn-1;i>=1;--i)
{
Finv[i]=Finv[i+1]*(i+1);
if(Finv[i]>=mod)Finv[i]%=mod;
}
}
ll C(ll n,ll m)
{
if(m<0||m>n)return 0;
return jc[n]*Finv[n-m]%mod*Finv[m]%mod;
}
int t,l,r,mx;
int pos[N];//pos[i]代表i下标所在的块号
ll res;
int sz;//块的大小
struct node
{
int l,r,id;
ll ans;
}e[N];
bool cmp1(node a,node b)
{
if(pos[a.l]==pos[b.l])
{
if(pos[a.l]&1)return a.r>b.r;
else return a.r<b.r;
}
return a.l<b.l;
}
bool cmp2(node a,node b)
{
return a.id<b.id;
}
int main()
{
init();
while(~scanf("%d",&t))
{
mx=0;
for(int i=1;i<=t;++i)
{
scanf("%d%d",&e[i].r,&e[i].l);
e[i].id=i;
mx=max(mx,e[i].r);
}
sz=(int)sqrt(mx);
for(int i=1;i<=mx;++i)
pos[i]=1+(i-1)/sz;
sort(e+1,e+t+1,cmp1);
l=1;r=1;res=2;
for(int i=1;i<=t;++i)
{
for(;r<e[i].r;r++)res=(2*res-C(r,l)+mod)%mod;
for(;r>e[i].r;r--)res=(res+C(r-1,l))%mod*inv2%mod;
for(;l<e[i].l;l++)res=(res+C(r,l+1))%mod;
for(;l>e[i].l;l--)res=(res-C(r,l)+mod)%mod;
e[i].ans=res;
}
sort(e+1,e+t+1,cmp2);
for(int i=1;i<=t;++i)
printf("%lld\n",e[i].ans);
}
return 0;
}