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.
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).
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
SOLUTION:
神仙题目
设s (n,m) 为所要求的值
发现不同的 s 之间可以互相的转移
应该可以联想到莫队离线
CODE:
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
using namespace std;
#define ll long long
#define mod 1000000007
const int maxn =100000+5;
ll ans[maxn],fac[maxn]={1,1},inv[maxn]={1,1},f[maxn]={1,1},len;
int T;
ll cal(ll a,ll b) //求组合数
{
if(b>a)
return 0;
return fac[a]*inv[b]%mod*inv[a-b]%mod;
}
void init()
{
for(int i=2; i<=maxn-1; i++)
{
fac[i]=fac[i-1]*i%mod;//阶乘
f[i]=(mod-mod/i)*f[mod%i]%mod;//逆元
inv[i]=inv[i-1]*f[i]%mod;//逆元的阶乘
}
}
struct Query
{
ll L,R,block;
int ID;
Query(){};
Query(ll l, ll r, int ID) :L(l), R(r), ID(ID){
block=l/len;
}
bool operator<(const Query rhs)const{
if(block ==rhs.block)
{
if(block&1) return R>rhs.R;
else return R<rhs.R;
}
return block <rhs.block;
}
}queries[maxn];
int main()
{
len=sqrt(maxn);///块长度
init();
scanf("%d",&T);
for(int i=1; i<=T; i++)
{
ll l,r;
scanf("%lld %lld",&l,&r);
queries[i]=Query(l,r,i);
}
sort(queries+1,queries+T+1);
int l=1 ,r=1;
ll val=2;
for(int i=1; i<=T; i++)
{
while(l<queries[i].L)
{
val=(2ll*val%mod+mod-cal(l,r))%mod;
l++;
}
while(l>queries[i].L)
{
--l;
val=(val+cal(l,r))%mod *f[2]%mod;
}
while(r<queries[i].R)
{
val=(val+cal(l,++r))%mod;
}
while(r>queries[i].R)
{
val=(val-cal(l,r--))%mod;
val+=mod;
val%=mod;
}
ans[queries[i].ID]=val;
}
for(int i=1; i<=T; i++)
printf("%lld
",ans[i]);
return 0;
}