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