洛谷 P9221 「TAOI-1」Pentiment 题解
Description
给定
对于所有数据,
link:https://www.luogu.com.cn/problem/P9221
Solution
算法一#
考虑朴素 DP,设
时间复杂度
算法二#
考虑优化算法一。对于每个 vector
即可。每次转移时使用双指针维护区间的和。
时间复杂度
算法三#
考虑
时间复杂度
算法四#
对有障碍的行跑算法二,没有障碍的行跑算法三即可。算法三有些改动,设当前行(有障碍)为
时间复杂度
算法五#
使用光速幂(分块预处理的快速幂),钦定
时间复杂度
Code
#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
namespace Milkcat {
typedef long long LL;
typedef pair<LL, LL> pii;
const int N = 1e6 + 5, mod = 998244353;
struct node { LL v, l, r; LL val() { return v * (r - l + 1); } }; // val:求整段区间数的和
LL n, m, q, qwq, cnt, ans, p1[N], p2[N]; pii a[N];
vector<node> vec, now;
LL qpow(LL k) { return p1[k % cnt] * p2[k / cnt] % mod; }
LL add(LL& x, LL y) { return x = ((x + y) % mod + mod) % mod; }
int main() {
cin >> n >> m >> q, cnt = sqrt(n) + 1, p1[0] = p2[0] = 1;
for (int i = 1; i <= cnt; i ++) p1[i] = p1[i - 1] * m % mod;
for (int i = 1; i <= cnt; i ++) p2[i] = p2[i - 1] * p1[cnt] % mod; // 光速幂
for (int i = 1; i <= q; i ++) cin >> a[i].fi >> a[i].se;
vec.push_back({1, 1, m}), qwq = 0; // 初值
for (int i = 1; i <= q; ) {
if (a[i].fi - qwq > 1) {
LL sum = 0, k = a[i].fi - qwq;
for (node v : vec) add(sum, v.val());
vector<node>().swap(vec), vec.push_back({sum * qpow(k - 2) % mod, 1, m});
} // 算法三
qwq = a[i].fi, vector<node>().swap(now);
LL l = 0, r = 0, pre = 1, sum = vec.front().val();
while (a[i].fi == qwq) {
if (pre < a[i].se) now.push_back({0, pre, a[i].se - 1});
now.push_back({-1, a[i].se, a[i].se}), pre = a[i].se + 1, i ++;
}
if (pre <= m) now.push_back({0, pre, m});
for (node &v : now) {
if (v.v == -1) { v.v = 0; continue; }
while (vec[l].r < v.l) add(sum, -vec[l ++].val());
while (vec[r].r < v.r) add(sum, vec[++ r].val());
v.v = ((sum - vec[l].v * (v.l - vec[l].l) - vec[r].v * (vec[r].r - v.r)) % mod + mod) % mod;
} // 算法二
vec.swap(now);
}
if (qwq < n) {
LL sum = 0, k = n - qwq + 1;
for (node v : vec) add(sum, v.val());
vector<node>().swap(vec), vec.push_back({sum * qpow(k - 2) % mod, 1, m});
} // 特判没有做完
for (node v : vec) add(ans, v.val());
cout << ans << '\n';
return 0;
}
}
int main() {
int T = 1;
while (T --) Milkcat::main();
return 0;
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步