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]);
}
}