There are nn apples on a tree, numbered from 11 to nn.
Count the number of ways to pick at most mm apples.
Input
The first line of the input contains an integer TT (1≤T≤105)(1≤T≤105) denoting the number of test cases.
Each test case consists of one line with two integers n,mn,m (1≤m≤n≤105)(1≤m≤n≤105).
Output
For each test case, print an integer representing the number of ways modulo 109+7109+7.
Sample Input
2 5 2 1000 500
Sample Output
16 924129523
题意:求C(n,0)+.....C(n,m);
思路:预处理+莫队
首先预处理阶乘和阶乘的逆元
定义S(n,m)为前m项之和,那么可以推出s(n,m)=2*s(n-1,m)-c(n-1,m)
也就是说,如果我们知道s(n,m),那么s(n+1,m)就可以知道了
所以离线处理,先按m的大小分块,再按n 从小到大排序
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <string>
#include <math.h>
#include <stack>
typedef long long ll;
using namespace std;
const int maxn=1e5+10;
const int INF=1e9;
const int mod=1e9+7;
const int MOD=1e9+7;
struct query
{
int n, k, id;
} q[maxn];
bool cmp(query a,query b)
{
return a.n<b.n;
}
int cnt, mx, chunk;
ll fac[maxn], inv[maxn], res[maxn], in_chunk[maxn];
vector <query> vec[maxn];
ll qpow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)
{
ans=ans*a%mod;
}
b>>=1;
a=a*a%mod;
}
return ans;
}
int C(int a, int b)
{
return 1ll * fac[a] * inv[b] % MOD * inv[a - b] % MOD;
}
void init()
{
mx = 100000;
fac[0] = 1;
for (int i = 1; i <= mx; ++ i) fac[i] = 1ll * fac[i - 1] * i % mod;
inv[mx] = qpow(fac[mx], MOD - 2);
for (int i = mx - 1; ~i; -- i) inv[i] = 1ll * inv[i + 1] * (i + 1) % MOD;
}
int main(int argc, char const *argv[])
{
init();
chunk = sqrt(mx);
cnt = 1;
for(int i=1;i<=mx;i+=chunk)
{
for(int j=i;j<i+chunk&&j<=mx;j++)
{
in_chunk[j]=cnt;
}
cnt++;
}
cnt-=1;
int T;
cin>>T;
for(int i=1;i<=T;i++)
{
scanf("%d%d",&q[i].n,&q[i].k);
q[i].id=i;
vec[in_chunk[q[i].k]].push_back(q[i]);//按k分块
}
for(int i=1;i<=cnt;i++)
{
if(vec[i].size())
{
sort(vec[i].begin(),vec[i].end(),cmp);
int ans=0,down=vec[i][0].n,up=-1;
for(int j=0;j<vec[i].size();j++)
{
while(down<vec[i][j].n)
{
ans=(0ll+ans+ans+mod-C(down++,up))%mod;
}
while(up<vec[i][j].k)
{
ans=(ans+C(down,++up))%mod;
}
while(up>vec[i][j].k)
{
ans=(ans-C(down,up--)+mod)%mod;
}
res[vec[i][j].id]=ans;
}
}
}
for(int i=1;i<=T;i++)
{
printf("%d\n",res[i]);
}
return 0;
}