題目鏈接:
2018 Multi-University Training Contest 4 Harvest of Apples HDU 6333
題意概括:
已知 n、m,求 。
數據範圍:
題解分析:
由於查詢次數很多,並且 n 的值可能很大,因此 普通在線 + 暴力遞推求組合數 肯定會超時,設
也就是 n , m 對應的答案。可以得到:
通過楊輝三角還可以得到:
推出由 O(1)轉換到 的公式
在相鄰狀態之間可以 O(1) 轉換的多詢問問題。很明顯,可以用莫隊算法。
莫隊算法就是先把所有詢問離線處理,經過特殊排序後,用左右兩個指針查詢。
複雜度: ,又名“優雅的暴力”
有兩個需要注意的地方:
- 有減號時應該先加上模數再取模
s = (2 * s - C(l, r) + MOD) % MOD;
-
(a / b) % MOD 不等於 (a % MOD / b % MOD) % MOD,正確的做法是乘上除數的逆元
s = ((s + C(l - 1, r)) * (int)(5e8 + 4)) % MOD; //除法不滿足取模,應該乘上逆元 inv[2]
AC代碼:
#include <stdio.h>
#include <math.h>
#include <algorithm>
#define max(a,b) (((a) > (b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
const int MOD = 1e9 + 7;
int fac[MAXN], finv[MAXN], block = -1;
ll ans[MAXN];
struct Query {
int l, r, id;
} Q[MAXN];
bool cmp(const Query& a, const Query& b) {
if ((a.l - 1) / block == (b.l - 1) / block) return a.r < b.r;
else return a.l < b.l;
}
ll mod_pow(ll x, ll n) {
if (n == 0) return 1;
ll res = mod_pow(x * x % MOD, n / 2);
if (n & 1) res = res * x % MOD;
return res;
}
void init() {
fac[0] = 1;
for(int i = 1; i < MAXN; i ++)
fac[i] = (ll)fac[i - 1] * i % MOD;
finv[MAXN - 1] = (int)mod_pow(fac[MAXN - 1], MOD - 2);
for(int i = MAXN - 1; i > 0; i --)
finv[i - 1] = (ll) finv[i] * i % MOD;
}
ll C(int n, int m) {
if(n < 0 || m < 0 || m > n) return 0;
return (ll)fac[n] * finv[m] % MOD * finv[n - m] % MOD;
}
int main() {
int T;
scanf("%d", &T);
init();
for (int i = 1; i <= T; i ++) {
Q[i].id = i;
scanf("%d%d", &Q[i].l, &Q[i].r);
block = max(block, Q[i].l);
}
block = sqrt(block);
sort(Q, Q + T, cmp);
int l = 1, r =1;
ll s = 2; //初始狀態爲 2 個
for (int i = 1; i <= T; i ++) {
while (l < Q[i].l) {
s = (2 * s - C(l, r) + MOD) % MOD; //有減法時要加上後取模
l ++;
}
while (l > Q[i].l) {
s = ((s + C(l - 1, r)) * (int)(5e8 + 4)) % MOD; //除法不滿足取模,應該乘上逆元 inv[2]
l --;
}
while (r < Q[i].r) {
s = (s + C(l, r + 1)) % MOD;
r ++;
}
while (r > Q[i].r) {
s = (s - C(l, r) + MOD) % MOD;
r --;
}
ans[Q[i].id] = s;
}
for (int i = 1; i <= T; i ++)
printf("%lld\n",ans[i]);
}
Harvest of Apples
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
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 +7.
Sample Input
2
5 2
1000 500
Sample Output
16
924129523