Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1595 Accepted Submission(s): 603
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 .
Sample Input
2
5 2
1000 500
Sample Output
16
924129523
Source
2018 Multi-University Training Contest 4
题意:t组数据,每组给出n和m,求()
题解:
假设c是b的逆元 ①,根据费马小定理: 时, ② (p表示素数)
联立①②可得: 所以模(p-2)就好
然后回到这题,显而易见可以得到
根据组合数的递推公式,
把上式的变成或者 得到:
根据红字的公式用莫队离线操作
代码:
#include
#define mem(a, x) memset(a, x, sizeof(a))
#define rep(i,a,n) for (int i=a;i=a;i--)
using namespace std;
typedef long long ll;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
//------------------------------------head------------------------------------
const int N = 1e5+10;
ll fac[N], inv[N]; // fac 阶乘, inv 逆元
ll inv2, val, ans[N]; // inv2 除2的逆元,val 中间答案,ans 答案
int pos[N], t; // pos 分块
void init() {
// 除2的逆元
inv2 = powmod(2, mod-2);
// 预处理阶乘
fac[0] = fac[1] = 1;
rep (i, 2, N) fac[i] = i * fac[i-1] % mod;
// 求阶乘逆元
inv[N-1] = powmod(fac[N-1], mod-2);
per (i, 0, N-1) inv[i] = inv[i+1] * (i+1) % mod;
}
ll comb(int n, int m) { // c(n, m) = n!/(m! * (n-m)!)
return fac[n] * inv[m] % mod * inv[n-m] % mod;
}
struct node {
int l, r, id;
} Q[N];
bool cmp(node a, node b) {
if (pos[a.l] == pos[b.l]) return a.r < b.r;
return a.l < b.l;
}
void addL(int n, int m) { // S(n,m) = 2 * S(n-1,m) - C(n-1,m)
val = (2 * val % mod - comb(n-1, m) + mod) % mod;
}
void delL(int n, int m) { // S(n-1,m) = (S(n,m) + C(n-1,m)) / 2
val = (val + comb(n-1, m)) % mod * inv2 % mod;
}
void addR(int n, int m) { // S(n,m) = S(n,m-1) + C(n,m)
val = (val + comb(n, m)) % mod;
}
void delR(int n, int m) { // S(n,m-1) = S(n,m) - C(n, m)
val = (val - comb(n,m) + mod) % mod;
}
int main() {
init();
scanf("%d", &t);
int sz = sqrt(N);
rep (i, 1, t+1) {
scanf("%d%d", &Q[i].l, &Q[i].r);
pos[i] = i / sz;
Q[i].id = i;
}
sort(Q+1, Q+t+1, cmp);
int l = 1, r = 1;
val = 2; // c(1,0) + c(1,1)
rep (i, 1, t+1) {
while (l < Q[i].l) addL(++l, r);
while (l > Q[i].l) delL(l--, r);
while (r < Q[i].r) addR(l, ++r);
while (r > Q[i].r) delR(l, r--);
ans[Q[i].id] = val;
}
rep (i, 1, t+1) printf("%lld\n", ans[i]);
}