P9400 「DBOI」Round 1 三班不一般 做题笔记
最近搬运一些洛谷上的题解到这里来,一是增加我的博文数量,二是缓解一下我的博客园冷清的气氛。
我的做法和题解里的做法不一样,麻烦了许多。
首先看到连续的几盏灯刺眼就不行了,当然能够想到动态规划,设
当前这盏灯,可以刺眼也可以不刺眼,刺眼:
不刺眼的话,前面再多连续的刺眼都废了,所以:
然后就能得到
#include <iostream> #define int long long using namespace std; int n, a, b; int l[200005], r[200005]; int f[1005][1005];//前 i 盏,末尾有连续 j 盏刺眼 const int mod = 998244353; int fun (int x, int y, int z) { if (y <= z) return 0; if (x <= z) return y - z; return y - x + 1; } int fun_ (int x, int y, int z) {//x 到 y 中小于等于 z 的数的个数 if (x > z) return 0; return min (y, z) - x + 1; } signed main () { cin >> n >> a >> b; for (int i = 1; i <= n; i ++) cin >> l[i] >> r[i]; if (a == n + 1) { long long ans = 1; for (int i = 1; i <= n; i ++) { ans *= long (r[i] - l[i] + 1); ans %= mod; } cout << ans << "\n"; } else if (a == 1) { long long ans = 1; for (int i = 1; i <= n; i ++) { if (l[i] > b) ans = 0; else ans *= long (min (r[i], b) - l[i] + 1); ans %= mod; } cout << ans << "\n"; } else { long long ans = 0; f[0][0] = 1; for (int i = 1; i <= n; i ++) { for (int j = 1; j < a; j ++) { f[i][j] = f[i - 1][j - 1] * fun (l[i], r[i], b) % mod; } for (int j = 0; j < a; j ++) { f[i][0] += f[i - 1][j]; if (f[i][0] > mod) f[i][0] -= mod; } f[i][0] = f[i][0] * fun_ (l[i], r[i], b) % mod; } for (int i = 0; i < a; i ++) ans = (ans + dp[n][i]) % mod; cout << ans << "\n"; } return 0; }
接着来考虑怎么优化呢?我试了半天,这个东西不能用斜率,不能用四边形不等式,好像没啥好优化的,这时就要转换状态了。
根据正难则反的经典套路,我们再设
为了不重复的统计每一个刺眼的方案,如果一个方案有多个连续的
所以:
乱搞的方案数显然是
最近
状态转移方程:
其实把
初始化细节很多,大家仔细看下。状态转移方程较麻烦,不过代码还行:
#include <iostream> #define int long long using namespace std; int n, a, b; int l[200005], r[200005]; int f[200005], F[200005]; int luangao[200005]; int ciyanfangan[200005], zero[200005]; const int mod = 998244353; int ciyande (int x, int y, int z) { if (y <= z) return 0; if (x <= z) return y - z; return y - x + 1; } int buciyande (int x, int y, int z) { if (x > z) return 0; return min (y, z) - x + 1; } int q_pow (int x, int y) { if (y == 0) return 1; if (y & 1) return x * q_pow (x * x % mod, y >> 1) % mod; return q_pow (x * x % mod, y >> 1); } int inv (int x) {return q_pow (x, mod - 2);} signed main () { cin >> n >> a >> b; luangao[0] = 1; for (int i = 1; i <= n; i ++) { cin >> l[i] >> r[i]; luangao[i] = luangao[i - 1] * (r[i] - l[i] + 1) % mod; if (ciyande (l[i], r[i], b) == 0) zero[i] = 1; zero[i] += zero[i - 1]; } for (int i = 1; i + a - 1 <= n; i ++) { if (zero[i + a - 1] - zero[i - 1] != 0) continue; if (ciyanfangan[i - 1] != 0) { ciyanfangan[i] = ciyanfangan[i - 1] * inv (ciyande (l[i - 1], r[i - 1], b) ) % mod * ciyande (l[i + a - 1], r[i + a - 1], b) % mod; continue; } ciyanfangan[i] = 1; for (int j = i; j <= i + a - 1; j ++) ciyanfangan[i] = ciyanfangan[i] * ciyande (l[j], r[j], b) % mod; } for (int i = 0; i < a; i ++) f[i] = luangao[i]; f[0] = 1; F[a] = ciyanfangan[1]; f[a] = ( (luangao[a] - F[a]) % mod + mod) % mod; for (int i = a + 1; i <= n; i ++) { F[i] = (F[i - 1] * (r[i] - l[i] + 1) % mod + f[i - a - 1] * ciyanfangan[i - a + 1] % mod * buciyande (l[i - a], r[i - a], b) % mod); f[i] = ( (luangao[i] - F[i]) % mod + mod) % mod; } cout << f[n] << "\n"; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异