A8-4:跳房子
2026-05-11 13:44:59
发布于:浙江
2阅读
0回复
0点赞
第 4 题
题意分析
有 个格子排成一列,编号 到 。从第 个格子出发,每一步可以选择一个步长 跳到 (不能越过 )。集合 是 个互不相交区间 的并集。
求从第 格走到第 格的不同方案数,答案对 取模。
关键约束:
- (区间数很少!)
思路分析
状态设计
设 = 从第 个格子走到第 个格子的方案数。
- 初始:
- 目标:
朴素转移(不够快)
集合 大小最多可能达到 ,每个 需要 转移,总复杂度 ,会超时。
关键观察:S 是若干个连续区间的并
因为 ,所以:
内层是 这一段连续区间的和,可以用前缀和优化!
前缀和优化
定义 ,。
对每个区间 ,把 从 到 替换成下标 从 到 :
- 设 ,
- 若 ,则贡献为
每个状态 转移,总复杂度 ,轻松通过。
模运算注意点
减法可能产生负数,要先 + MOD 再取模:
(prefix[hi] - prefix[lo-1] + MOD) % MOD
代码实现(逐行解释)
#include <bits/stdc++.h>
using namespace std;
const int MOD = 998244353; // 题目要求的模数
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, K;
cin >> N >> K;
// 读入 K 个区间 [L_j, R_j]
vector<int> L(K), R(K);
for (int j = 0; j < K; j++) {
cin >> L[j] >> R[j];
}
// dp[i] = 走到第 i 个格子的方案数
// pre[i] = dp[1] + dp[2] + ... + dp[i],pre[0] = 0
vector<long long> dp(N + 1, 0);
vector<long long> pre(N + 1, 0);
// 初始状态:在第 1 个格子,方案数为 1
dp[1] = 1;
pre[1] = 1;
// 从 i=2 开始递推
for (int i = 2; i <= N; i++) {
long long val = 0;
// 枚举每个区间 [L_j, R_j]
for (int j = 0; j < K; j++) {
// 步长 d 在 [L_j, R_j] 范围内,对应 i-d 在 [i-R_j, i-L_j]
// 同时要求 i-d >= 1,即下标至少为 1
int lo = max(1, i - R[j]); // 下标下界
int hi = i - L[j]; // 下标上界
// 只有当 lo <= hi 时区间才非空(即至少有一个合法的 d)
if (lo <= hi) {
// 用前缀和 O(1) 求 dp[lo] + dp[lo+1] + ... + dp[hi]
// +MOD 是为了防止减法出现负数
val = (val + pre[hi] - pre[lo - 1] + MOD) % MOD;
}
}
dp[i] = val;
pre[i] = (pre[i - 1] + dp[i]) % MOD; // 更新前缀和
}
cout << dp[N] << endl;
return 0;
}
这里空空如也


有帮助,赞一个