Problem Description
There are n apples on a tree, numbered from 1 to n .
Count the number of ways to pick at most m apples.
Input
The first line of the input contains an integer T (1≤T≤105) denoting the number of test cases.
Each test case consists of one line with two integers n,m (1≤m≤n≤105) .
Output
For each test case, print an integer representing the number of ways modulo 109+7 .
Sample Input
2
5 2
1000 500
Sample Output
16
924129523
题解:题目要求累加组合C(n,m)m的范围(0,m);所以如果用莫队最重要的是 弄清相邻的总和之间的关系
并且要明白组合是如何在编程中实现的,例如C(n,m)为1到n的累乘,乘以n-m的逆元进行mod运算,乘以m的逆元再进行mod运算。
逆元则是当前数的mod-2次方,最好在用之前就把累乘表和逆元表打好;
#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define maxn 100005
#define ll long long
ll inv[maxn],fas[maxn],ans[maxn];
int pos[maxn];//记录数据所属的块
struct node
{
int n,m,id;
}a[maxn];
bool cmp(node o,node p)
{
return pos[o.n]==pos[p.n]?o.m<p.m:o.n<p.n;
}
ll qpow(ll a,ll b)//快速幂
{
ll ans=1;
while(b)
{
if(b&1)
{
ans=ans*a%mod;
}
a=a*a%mod;
b>>=1;
}
return ans;
}
void init()
{
fas[1]=1;
for(int i=2;i<maxn;i++)//累乘表
{
fas[i]=i*fas[i-1]%mod;
}
for(int i=1;i<maxn;i++)//逆元表
{
inv[i]=qpow(fas[i],mod-2);
}
}
ll C(int n,int m)//组合运算
{
if(n<=0||n<m||m<0)
{
return 0;
}
if(m==0||n==m)
{
return 1;
}
return fas[n]*inv[n-m]%mod*inv[m]%mod;
}
int main()
{
init();
int block=sqrt(maxn),t;
cin>>t;
for(int i=1;i<maxn;i++)//进行莫队的划块
{
pos[i]=(i-1)/block;
}
for(int i=1;i<=t;i++)
{
scanf("%d %d",&a[i].n,&a[i].m);
a[i].id=i;
}
sort(a+1,a+1+t,cmp);//莫队排序
int st=1,en=0;
ll dns=1;
for(int i=1;i<=t;i++)
{
while(st<a[i].n)
{
dns=(2*dns-C(st++,en)+mod)%mod;
}
while(st>a[i].n)
{
dns=(dns+C(--st,en))*inv[2]%mod;
}
while(en<a[i].m)
{
dns=(dns+C(st,++en))%mod;
}
while(en>a[i].m)
{
dns=(dns-C(st,en--)+mod)%mod;
}
ans[a[i].id]=dns;
}
for(int i=1;i<=t;i++)//输出结果
{
printf("%lld\n",ans[i]);
}
}