@Harvest of Apples@
@题目描述 - English@
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≤10^5) denoting the number of test cases.
Each test case consists of one line with two integers n,m (1≤m≤n≤10^5).
Output
For each test case, print an integer representing the number of ways modulo 10^9+7.
Sample Input
2
5 2
1000 500
Sample Output
16
924129523
@大致题意@
T组询问,每组询问包含n, m。求:
T,n,m <= 10^5
@分析@
这么优美的式子居然没有通项公式!
它!居然!没有通项公式!!!
没有通项公式的话……我们也只能考虑暴力一点的做法……
我们令
,
则有:
反过来可知
反过来可知
我们可以通过预处理阶乘及逆元O(1)求出
。
那么上面的式子就告诉我们,如果我们已知
,则可以O(1)求出
。
这个特征其实就是莫队算法的特征。尽管问题询问的不是区间,但我们仍然可以使用莫队算法解决。
具体的话,就是把n看成区间左端点,m看成区间右端点,其他的大致细节就是按照莫队算法来。
@代码@
【学过不会用系列】
如果有什么问题可以参考代码细节,或也可以留言在下面询问。我会尽力解答问题的OuO
#include<cstdio>
#include<algorithm>
using namespace std;
const int BLOSIZ = 320;
const int MAXN = 100000;
const int MOD = int(1E9) + 7;
struct node{
int le, ri;
int id;
}qry[MAXN + 5];
bool operator < (node a, node b) {
if( a.le / BLOSIZ == b.le / BLOSIZ )
return a.ri < b.ri;
else return a.le < b.le;
}
int fact[MAXN + 5], inv[MAXN + 5];
int pow_mod(int b, int p) {
int ret = 1;
while( p ) {
if( p & 1 )
ret = 1LL * ret * b % MOD;
b = 1LL * b * b % MOD;
p >>= 1;
}
return ret;
}
void Init() {
fact[0] = 1;
for(int i=1;i<=MAXN;i++)
fact[i] = 1LL * fact[i-1] * i % MOD;
inv[MAXN] = pow_mod(fact[MAXN], MOD-2);
for(int i=MAXN-1;i>=0;i--)
inv[i] = 1LL * inv[i+1] * (i+1) % MOD;
}
int Comb(int n, int m) {
if( n < m ) return 0;
else return 1LL * fact[n] * inv[m] % MOD * inv[n-m] % MOD;
}
int ans[MAXN + 5];
int le, ri, sum;
int main() {
Init(); int T;
scanf("%d", &T);
for(int i=1;i<=T;i++) {
scanf("%d%d", &qry[i].le, &qry[i].ri);
qry[i].id = i;
}
sort(qry+1, qry+T+1);
le = ri = 0, sum = 1;
for(int i=1;i<=T;i++) {
while( ri < qry[i].ri ) {
sum = (sum + Comb(le, ri+1)) % MOD;
ri++;
}
while( ri > qry[i].ri ) {
sum = (sum - Comb(le, ri)) % MOD;
ri--;
}
while( le < qry[i].le ) {
sum = (2LL*sum - Comb(le, ri)) % MOD;
le++;
}
while( le > qry[i].le ) {
sum = 1LL*(sum + Comb(le-1, ri))*inv[2] % MOD;
le--;
}
ans[qry[i].id] = sum;
}
for(int i=1;i<=T;i++)
printf("%d\n", (ans[i] + MOD) % MOD);
}
@END@
就是这样,新的一天里,也请多多关照哦(ノω<。)ノ))☆.。~