首页 > 其他分享 >AT_abc321_f [ABC321F] #(subset sum = K) with Add and Erase 题解

AT_abc321_f [ABC321F] #(subset sum = K) with Add and Erase 题解

时间:2023-09-24 09:22:06浏览次数:61  
标签:subset int 题解 sum 权值 物品 dp mod

AT_abc321_f [ABC321F] #(subset sum = K) with Add and Erase 题解

题目大意

现在有一个空箱子。给你两个数 \(Q, K\),然后给你 \(Q\) 行,每一行代表一个操作:

  • \(+ x\),即向箱子里加一个权值为 \(x\) 的小球。

  • \(- x\),即从箱子里把权值为 \(x\) 的小球拿一个出来。保证合法,即箱子里一定有权值为 \(x\) 的小球。

每一次操作后你都需要输出存在多少种拿球的方案,使得你拿出的所有球的权值和为 \(K\)。答案对 \(998244353\) 取模。

\(1 \le Q, K, x \le 5000\)

题解

如果不是动态的话,明显是普通的 0-1 背包问题。

考虑怎么让 0-1 背包变得动态。

我们发现这其实就是一个加减物品的操作。

加物品非常简单,就是再在原基础上跑一遍 dp。

            for(int i = 5000; i >= x; -- i)
                if(dp[i - x])
                    dp[i] = (dp[i] + dp[i - x]) % mod;

减物品其实也不难。就相当于跑了一遍反着的加物品。换句话说,就是你要在原有的方案上,减去这个物品贡献的方案。

            for(int i = x; i <= 5000; ++ i)
                if(dp[i - x])
                    dp[i] = (dp[i] - dp[i - x] + mod) % mod;

注意一些细节。加物品需要从大往小枚举,防止算重,和普通 0-1 背包一样。而减物品需要为了防止算重需要从小到大枚举。

代码

#include <bits/stdc++.h>
#define int long long
#define M 10005
#define mod 998244353

using namespace std;

int Q, K, dp[M], x;
char ch;

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    cin >> Q >> K;
    dp[0] = 1;
    for(int i = 1; i <= Q; ++ i) {
        cin >> ch >> x;
        if(ch == '+') {
            for(int i = 5000; i >= x; -- i)
                if(dp[i - x])
                    dp[i] = (dp[i] + dp[i - x]) % mod;
        }
        else
            for(int i = x; i <= 5000; ++ i)
                if(dp[i - x])
                    dp[i] = (dp[i] - dp[i - x] + mod) % mod;
        cout << dp[K] << '\n';
    }
}

标签:subset,int,题解,sum,权值,物品,dp,mod
From: https://www.cnblogs.com/Meteor-streaking/p/17725601.html

相关文章

  • CF877F 题解
    CF877F题解更好的阅读体验提供一个扫描线+根号分治做法。首先,可以把题目的条件转化成求$sum_r-sum_{l-1}=k$的区间数。考虑扫描线,当区间的右端点从$r-1$移动到$r$时,新增的区间的左端点就是所有满足$sum_{l-1}=sum_r-k,l\ler$的$l$。这时我们对$sum_{l-1}$......
  • 【问题解决】shell脚本执行错误 $‘\r‘:command not found
    问题原因:在Windows中,换行符是由回车符(\r)和换行符(\n)组成的,而在Unix/Linux等系统中,只使用换行符(\n)作为换行标志。当你在Unix/Linux系统上运行一个包含Windows格式换行符的脚本时,Shell会尝试解释其中的回车符,导致错误提示$‘\r’:commandnotfound。这是因为Shell将回......
  • [COCI2016-2017#4] Osmosmjerka 题解
    [COCI2016-2017#4]Osmosmjerka题解我们发现对于每个点,只有八个方向,也就是说,最终能得到的字符串只会有\(8nm\)个,那我们可以考虑把这些字符串的哈希值求出来,相同的哈希值代表选到相同字符串的一种可能,直接统计即可。现在的问题就在于,怎么快速地求出这\(8nm\)个字符串的哈希......
  • 题解 CF1257G【Divisor Set】
    problem我们说一个集合\(D\)是一个好的集合,当不存在集合中的两个不同元素\(a,b\)使得\(a\)是\(b\)的约数。给定一个超大整数的素数表示形式\(N=\prod_{i=1}^n{p_i}\),要求从它的所有因子中选择尽可能多的元素组成一个好的集合。问这个最大的size是多少,输出模99824......
  • 题解 ARC165F【Make Adjacent】
    区间排序问题,主席树优化建图,最小字典序拓扑排序(priority_queue)problem给定一个长度为\(n*2\)的序列,其中每种元素恰好出现了2次。允许每次选择任意两个相邻的元素交换。那么必定存在一个最小\(k\):使得\(k\)次交换以后所有相同的元素都是相邻的。问恰好操作\(k\)次后,......
  • P6667 [清华集训2016] 如何优雅地求和 -Binomial Sum
    题面有一个多项式函数\(f(x)\),最高次幂为\(x^m\),定义变换\(Q\):\[Q(f,n,x)=\sum_{k=0}^{n}f(k)\binom{n}{k}x^k(1-x)^{n-k}\]现在给定函数\(f\)和\(n,x\),求\(Q(f,n,x)\bmod998244353\)。出于某种原因,函数\(f\)由点值形式给出,即给定\(a_0,a_1,⋯,a_m\)共\(m+1\)个......
  • 【POJ 1521】Entropy 题解(贪心算法+优先队列+哈夫曼树)
    熵编码器是一种数据编码方法,通过对删除了“浪费”或“额外”信息的消息进行编码来实现无损数据压缩。换句话说,熵编码去除了最初不需要的信息,以准确编码消息。高度的熵意味着一条消息包含大量浪费的信息;以ASCII编码的英文文本是具有极高熵的消息类型的示例。已经压缩的消息,如JPEG图......
  • 题解 CF1873H Mad City
    题意描述马塞尔和瓦勒里乌(Valeriu)所在的疯狂城市由\(n\)栋建筑和\(n\)条双向道路组成。马塞尔和瓦勒里乌(Valeriu)分别从\(a\)号和\(b\)号建筑开始。马塞尔想赶上瓦勒里乌(换句话说,与他在同一栋楼里或在同一条路上相遇)。在每次移动过程中,他们都会选择前往当前建筑的邻近建......
  • 'main' attribute cannot be used in a module that contains top-level code 问题解
    核心是@main注解在main.swift文件中,可以重新命名下参考资料https://stackoverflow.com/questions/73431031/swift-cli-app-main-attribute-cannot-be-used-in-a-module-that-contains-top-leve......
  • CF1842F Tenzing and Tree 题解
    TenzingandTree感觉很典型的题,就是树的重心+绝对值等式解法:以每个点\(i\)为根分别\(bfs\),得到一个距离数组\(dis\),取前\(k\)个值的权值为和,更新\(w[k]\)的值,\(n\)个点分别为根,更新\(n\)遍之后,得到\(w\)数组,则\((n-1)\timesi-w[i]\),即为\(i\)个点时候的......