Typesetting math: 100%

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

思路

可撤销背包板子。

首先问题是用当前所拥有的数的集合凑出 xx 的方案数。

这个问题明显可以背包解决,即 dpjdpj+dpjaidpjdpj+dpjai

但是,此问题中物品有可能会被删除,即变为了一个动态的问题,如果直接暴力计算时间复杂度为 Θ(qn2)Θ(qn2)

那么,我们转化一下思路,如果我们使每一次变化的数 xx 都假令为 aa 中的最后一个元素。因为 0-1 背包对于数的先后顺序无关,所以此假令不会影响答案。

然后,再想一下 0-1 背包的板子,我们已经假令 xxaa 中最后一位元素,如果 aa 的大小为 mm,那么我们在枚举 ii 时,当 ii[1,m)[1,m) 范围内时,此时更新的 DP 数组与原 DP 数组的值不变。

因此,我们只需要考虑 xx 带来的贡献,我们将两种操作分开考虑。

Part 1 添加操作#

因为是在 0-1 背包里面取出最后一个元素,所以与 0-1 背包相同。

for (re int i = n;i >= x;i--) dp[i] = Add(dp[i],dp[i - x]);  

Part 2 删除操作#

因为是删除,所以枚举的顺序也不同。

设想如果按照正常 0-1 背包的顺序枚举,当此时删除 22 时,如果能删除 dp9dp9 就会被 dp7dp7 所影响,但如果 aa 中只有一个 22,显然 dp9dp9 无法取到。

那么当倒序循环时,dp9dp9 会在 dp7dp7 之后计算到。

for (re int i = x;i <= n;i++) dp[i] = Sub(dp[i],dp[i - x]);  

Code

#include <bits/stdc++.h>  
#define re register  
#define int long long  
  
using namespace std;  
  
const int N = 5010,mod = 998244353;  
int q,n;  
int dp[N];  
  
inline int read(){  
    int r = 0,w = 1;  
    char c = getchar();  
    while (c < '0' || c > '9'){  
        if (c == '-') w = -1;  
        c = getchar();  
    }  
    while (c >= '0' && c <= '9'){  
        r = (r << 3) + (r << 1) + (c ^ 48);  
        c = getchar();  
    }  
    return r * w;  
}  
  
inline int Add(int a,int b){  
    return (a + b) % mod;  
}  
  
inline int Sub(int a,int b){  
    return ((a - b) % mod + mod) % mod;  
}  
  
signed main(){  
    dp[0] = 1;  
    q = read();  
    n = read();  
    while (q--){  
        int x;  
        char op[10];  
        scanf("%s",op);  
        x = read();  
        if (op[0] == '+'){  
            for (re int i = n;i >= x;i--) dp[i] = Add(dp[i],dp[i - x]);  
        }  
        else{  
            for (re int i = x;i <= n;i++) dp[i] = Sub(dp[i],dp[i - x]);  
        }  
        printf("%lld\n",dp[n]);  
    }  
    return 0;  
}  

作者:WaterSun

出处:https://www.cnblogs.com/WaterSun/p/18262943

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   WBIKPS  阅读(10)  评论(0编辑  收藏  举报
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示