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,0),c(n,1),,,c(n,m);
做法:分块,B = 333,预处理dp[i][j]代表c(i*B,j),用逆元需要n*B的复杂度。
然后对于c(n,m),可以把n分成两部分,一部分为p=n/B*B;一部分是q = n%B,
那么有c(n,m) = c(p,x)*c(q,y){x+y == m}成立,那么可以推出c(n,0)+c(n,1),,,+c(n,m) = c(p,x)*c(q,y){x+y <= m} 成立;因为q< B;
所以预处理c(p,x) 的前缀和,枚举y的值,就可以在n*B的复杂度下得到答案了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N= 1e5+100;
const int mod = 1e9+7;
int bp[335][335];
int dp[335][N];
ll f[N],invf[N],inv[N];
void add(int &x,int y){
x += y;
if(x >= mod) x -= mod;
}
void init(){
dp[0][0] = 1;
inv[1] = 1;
f[0] = invf[0] = 1;
for(int i = 2;i < N;i ++){
inv[i] = (mod-mod/i)*1LL*inv[mod%i]%mod;
}
for(int i =1;i < N;i ++){
f[i] = f[i-1]*i%mod;
}
for(int i = 1;i < N;i ++){
invf[i] = invf[i-1]*1LL*inv[i]%mod;
}
for(int i = 1;i < 100333/333;i ++){
for(int j = 0;j <= 1e5;j ++){
dp[i][j] = f[i*333]*invf[j]%mod*invf[i*333-j]%mod;
}
}
for(int i = 1;i < 100333/333;i ++){
for(int j = 1;j <= 1e5;j ++){
add(dp[i][j],dp[i][j-1]);
}
}
bp[0][0] = 1;
for(int i = 1;i <= 333;i ++){
for(int j= 0;j<= 333;j ++){
bp[i][j] = bp[i-1][j];
if(j) add(bp[i][j],bp[i-1][j-1]);
}
}
}
int main(){
init();
//cout << dp[1][2] << endl;
int T;
cin >>T;
while(T--){
int n,m;
scanf("%d %d",&n,&m);
int b = n/333;
int res = n-b*333;
int ans = 0;
if(n <= 333) {
for(int i = 0;i <= m;i ++){
add(ans,bp[n][i]);
}
}
else{
int fir = 0;
if(m <= b*333) fir = 0;
else fir = m%333;
for(int i = 0;i <= min(res,m);i ++){
add(ans,1LL*bp[res][i]*dp[b][min(m-i,b*333)]%mod);
}
}
printf("%d\n",ans);
}
return 0;
}