【HDU - 6333】Harvest of Apples
@Harvest of [email protected]
@題目描述 - [email protected]
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);
}
@[email protected]
就是這樣,新的一天裡,也請多多關照哦(ノω<。)ノ))☆.。~