AtCoder ABC321F - #(subset sum = K) with Add and Erase 题解 回滚背包

题目链接:https://atcoder.jp/contests/abc321/tasks/abc321_f

题目大意:

给定大小为 \(k\) 的背包和 \(q\) 次操作,支持两种操作:

  • 插入一个大小为 \(x\) 的元素;
  • 删除一个大小为 \(x\) 的元素。

每次操作后,求装满背包方案数。

解题思路:

可撤销背包。

  • 插入 \(x\) 时,for i = K -> x 执行 f[i] += f[i-x]
  • 删除 \(x\) 时,for i = x -> K 执行 f[i] -= f[i-x]

(虽然我代码里是用 V 表示背包容量的)

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5050;
const long long mod = 998244353;

int q, V, x;
char op[2];
long long f[maxn] = { 1 };

int main() {
    scanf("%d%d", &q, &V);
    while (q--) {
        scanf("%s%d", op, &x);
        if (op[0] == '+') {
            for (int i = V; i >= x; i--)
                f[i] = (f[i] + f[i-x]) % mod;
        }
        else {
            for (int i = x; i <= V; i++)
                f[i] = (f[i] - f[i-x] + mod) % mod;
        }
        printf("%lld\n", f[V]);
    }
    return 0;
}

双倍经验:洛谷P4141 消失之物

参考资料:可撤销背包学习笔记 作者:Nicrobot

posted @ 2024-11-25 10:06  quanjun  阅读(9)  评论(0编辑  收藏  举报