HDU 6333 Harvest of Apples [ 莫队算法 ]
题目链接:
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
Source
上一篇: 爱恍如隔世了要如何重燃爱火?
下一篇: 结婚了天天吵架想离婚怎么办