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≤
105
10
5
) denoting the number of test cases.
Each test case consists of one line with two integers n,m (1≤m≤n≤
105
10
5
).
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;
}