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≤ ) denoting the number of test cases.
Each test case consists of one line with two integers n,m (1≤m≤n≤ ).
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
Source
2018 Multi-University Training Contest 4
Solution
莫隊
可以使用莫隊離線處理1e5個詢問,將將n^2的時間複雜度降到n*sqrt(n),從整個兒的大無序區間到sqrt(n)個對外有序對內無序的小區間;
鄙人由此題始知一二,仍甚不熟悉,還需多學多練。
組合數學
公式推導如下圖
Code
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod = 1000000007;
const int N = 100001;
int T, x, curL, curR;
int pos[N];
ll res, ans[N], fac[N], inv[N];
struct data {
int L, R, id;
bool operator<(const data &b) const {
if (pos[L] == pos[b.L]) return R < b.R;
return L < b.L;
}
} q[N];
ll fun(ll a, ll k) {
ll res = 1;
while (k) {
if (k & 1) res = res * a % mod;
a = a * a % mod;
k >>= 1;
}
return res;
}
ll Comb(int n, int m) {
return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
inline void addN(int l, int r) {
res = (res + res - Comb(l, r) + mod) % mod;
}
inline void delN(int l, int r) {
res = (res + Comb(l - 1, r)) * inv[2] % mod;
}
inline void addM(int l, int r) {
res = (res + Comb(l, r + 1)) % mod;
}
inline void delM(int l, int r) {
res = (res - Comb(l, r) + mod) % mod;
}
int main() {
//freopen("../in", "r", stdin);
fac[0] = inv[0] = 1;
for (int i = 1; i < N; ++i) fac[i] = fac[i - 1] * i % mod;
inv[N - 1] = fun(fac[N - 1], mod - 2);
for (int i = N - 2; i > 0; --i) inv[i] = inv[i + 1] * (i + 1) % mod;
x = sqrt(N);
scanf("%d", &T);
for (int i = 0; i < T; ++i) {
q[i].id = i;
pos[i] = i / x;
scanf("%d%d", &q[i].L, &q[i].R);
}
sort(q, q + T);
res = 2, curL = 1, curR = 1;
for (int i = 0; i < T; ++i) {
while (curL < q[i].L) addN(curL++, curR);
while (curL > q[i].L) delN(curL--, curR);
while (curR < q[i].R) addM(curL, curR++);
while (curR > q[i].R) delM(curL, curR--);
ans[q[i].id] = res;
}
for (int i = 0; i < T; ++i) printf("%lld\n", ans[i]);
return 0;
}