HDU6333 - 莫队算法
Harvest of Apples
题目大意
给你n,m求。
数据范围
T组数据。
解题思路
这题常规思路暴力求前缀和时间复杂度和空间复杂度都是显然不够的,所以,采用莫队算法将T个询问排序,之后将m看做l,n看做r,通过观察可以发现
所以首先将r加/减到指定行,之后对l进行加/减,设res为答案,即:
r加的时候:
r减的时候:
l加的时候:
l减的时候:
具体见代码:
AC代码
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 100000;
const int Pt = 1e9 + 7;
struct NOOD {
int l, r, id;
}q[maxn + 5];
LL P[maxn + 5], rP[maxn + 5];
int T;
int B[maxn + 5];
LL qwe(LL x, LL y) {
LL res = 1;
while(y > 0) {
if(y & 1)res = res * x % Pt;
y >>= 1;
x = x * x % Pt;
}
return res;
}
bool cmp(NOOD a, NOOD b) {
if(B[a.l] == B[b.l])return a.r < b.r;
else return a.l < b.l;
}
void Init() {
P[0] = 1; rP[0] = qwe(P[0], Pt - 2);
for(int i = 1; i <= maxn; i++) {
P[i] = P[i - 1] * i % Pt;
rP[i] = qwe(P[i], Pt - 2);
}
int unit = sqrt(maxn);
for(int i = 1; i <= maxn; i++)B[i] = i / unit + 1;
scanf("%d", &T);
for(int i = 1; i <= T; i++)scanf("%d%d", &q[i].r, &q[i].l), q[i].id = i;
sort(q + 1, q + T + 1, cmp);
}
LL C(int n, int m) {
return P[n] * rP[n - m] % Pt * rP[m] % Pt;
}
vector<pair<int, LL> > ans;
int main() {
LL res = 0;
Init();
int l = q[1].l, r = q[1].r;
for(int i = 0; i <= l; i++)res = (res + C(r, i)) % Pt;
ans.push_back(make_pair(q[1].id, res));
for(int i = 2; i <= T; i++) {
while(r < q[i].r) {
res = ((res * 2 - C(r, l)) % Pt + Pt) % Pt;
r++;
}
while(r > q[i].r) {
r--;
res = (res + C(r, l)) % Pt * rP[2] % Pt;
}
while(l < q[i].l) {
l++;
res = (res + C(r, l)) % Pt;
}
while(l > q[i].l) {
res = ((res - C(r, l)) % Pt + Pt) % Pt;
l--;
}
ans.push_back(make_pair(q[i].id, res));
}
sort(ans.begin(), ans.end());
for(int i = 0; i < ans.size(); i++)printf("%lld\n", ans[i].second);
return 0;
}