专栏文章
题解:AT_arc204_a [ARC204A] Use Udon Coupon
AT_arc204_a题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @minomvw6
- 此快照首次捕获于
- 2025/12/02 05:49 3 个月前
- 此快照最后确认于
- 2025/12/02 05:49 3 个月前
观察基本条件。相当于是各实施 次操作 1 和操作 2。然后在任意时刻你已经实施的操作 2 次数不能大于操作 1 的次数。
参照 Iniaugoty 大佬的思路(最好先看一下他的题解,看懂就不用看我的了),把操作 1 想象成一条斜上的直线,操作 2 想象成斜下的直线。
由于每次我们 x 轴方向和 y 轴方向移动的距离相等,所以斜率也是相等的,只有斜上和斜下之分。把图画出来大概长这样。
注释:我这里要说一下,我画完图之后才发现自己画的不严谨,第一次操作只能是操作 1, 因此图像的第一个折线应该只能是斜下的。不过懒得重画了,领会精神即可。
图像画出来大概长成这个样子(蓝)。

题目中的条件 “将 替换为 “, 其实就相当于图像碰到 x 轴之后不继续往下,而是水平向右延申。
那么图像其实就长成这个样子(红)。

你发现,最右边那一段,红色的图像是比蓝色要长的。这长的一段距离,也就是蓝色图像在 x 轴以下的距离。
因为我们只考虑结束点的 y 值,也就是 的最终值,所以我们可以直接把蓝色图像向上平移。得到绿色图像。

绿色图像的结束点和红色图像的结束点的 y 值一样。
我们考虑到平移的距离其实就是蓝色最低点离 x 轴的距离,那么我们设它为 。
由此表示绿色图像的最终点纵坐标,也就是红色图像的最终点纵坐标,也就是 。
然后把 代入题目中的不等式,解得
这个不等式容斥做一下就行。
然后我们就 dp 呗,计算已经实施了前 个操作 1, 前 个操作 2 ,并且满足限制条件的方案数。
小细节是,发现不满足限制条件要直接 continue 掉,也不能给后面转移。因为我们设 是全局的最小值,如果有小于它的值一定不合法。
CPP#include <bits/stdc++.h>
#define int long long
#define rep(i, a, b) for(register int i = a; i <= b; ++i)
using namespace std;
constexpr int N = 5005, mod = 998244353;
int ans, n, l, r, L, R, suma[N], sumb[N], f[N][N], g[N][N];
inline void gm(int &x) {
if(x >= mod) {
x -= mod;
}
}
signed main() {
cin >> n >> L >> R;
rep(i, 1, n) {
cin >> suma[i];
suma[i] += suma[i - 1];
}
rep(i, 1, n) {
cin >> sumb[i];
sumb[i] += sumb[i - 1];
}
l = sumb[n] - suma[n] - R, r = sumb[n] - suma[n] - L + 1;
f[0][0] = g[0][0] = 1;
rep(i, 1, n) {
rep(j, 0, i) {
if(sumb[j] - suma[i] < l) continue;
if(j) {
f[i][j] = f[i][j] + f[i][j - 1];
gm(f[i][j]);
}
f[i][j] = f[i][j] + f[i - 1][j];
gm(f[i][j]);
}
}
rep(i, 1, n) {
rep(j, 0, i) {
if(sumb[j] - suma[i] < r) continue;
if(j) {
g[i][j] = g[i][j] + g[i][j - 1];
gm(g[i][j]);
}
g[i][j] = g[i][j] + g[i - 1][j];
gm(g[i][j]);
}
}
cout << (f[n][n] - g[n][n] + mod) % mod;
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...