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
题目大概:
给出T组数据,每组数据一个n 和一个 m,计算C(n,0)+C(n,1)+.....+C(n,m),%1e9+7。
思路:
刚开始很容易想到分块,发现是离线询问,指针的跳动也可以O(1)实现,那么就可以用莫队解决。
这是杨辉三角,杨辉三角的前缀和,可以推出前一项和后一项的关系,毕竟是前缀和,比较容易推。
直接预处理,分块莫队就行了。
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+100;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
int fac[maxn],inv[maxn],be[maxn],ans[maxn];
int inv2;
struct poin
{
int n,m,id;
} G[maxn];
bool cmp(const poin &a,const poin &b)
{
if(be[a.n]==be[b.n])return a.m<b.m;
else return a.n<b.n;
}
long long pow_mod(long long a,long long b,long long m)
{
a=a%m;
long long ans=1;
while(b)
{
if(b&1)
{
ans=(ans*a)%m;
b--;
}
b>>=1;
a=a*a%m;
}
return ans;
}
ll C(int n,int m)
{
return (1LL*fac[n]*inv[m]%mod*inv[n-m])%mod;
}
void init()
{
int mx=100000;
fac[0]=1;
for(int i=1; i<=mx; i++)
{
fac[i]=(1LL*fac[i-1]*i)%mod;
}
inv2=pow_mod(2,mod-2,mod);
inv[mx]=pow_mod(fac[mx],mod-2,mod);
for(int i=mx-1; ~i; i--)inv[i]=(1LL*inv[i+1]*(i+1))%mod;
int block=sqrt(mx);
for(int i=1; i<=mx; i++)
{
be[i]=i/block;
}
}
int main()
{
int T;
init();
scanf("%d",&T);
for(int i=1; i<=T; i++)
{
scanf("%d%d",&G[i].n,&G[i].m);
G[i].id=i;
}
sort(G+1,G+1+T,cmp);
int n=1,m=1;
int sum=2;
for(int i=1; i<=T; i++)
{
while(n<G[i].n)sum=( 0LL + 2*sum + mod - C(n++,m)) % mod;
while(n>G[i].n)sum= ( sum + C(--n, m)) % mod * inv2 % mod;
while(m<G[i].m) sum =(sum + C(n, ++m )) % mod;
while(m>G[i].m)sum =(sum + mod - C(n, m-- )) % mod;
ans[G[i].id]=sum;
}
for(int i=1;i<=T;i++)
{
printf("%d\n",ans[i]);
}
return 0;
}