首页 > 其他分享 >ABC 321 F #(subset sum = K) with Add and Erase

ABC 321 F #(subset sum = K) with Add and Erase

时间:2024-06-13 16:59:15浏览次数:23  
标签:subset 遍历 int sum 那么 cin ABC 添加 dp

题意
有一个箱子,每次可以向里面添加或者拿走一个数,问每次操作过后,任选箱子里的数相加,总和等于k的方案数是多少。

思路
萌新算是学到新东西了,这其实是个可撤销背包的板题。
我们先考虑一个问题:
对于普通计数类dp,我们现在禁用某一个数i,我们现在想知道某一个数j有多少种方式表示(即dp[j])。那么我们现在正常进行一次计数dp,然后撤销使用了数字i的方案即可。

  • 若j<i,那么dp[j]是不会变化的,因为j不可能表示为i加上其它正整数的和
  • 若j>=i,dp[j]就会包含选择了数字i的方案。那么这些方案一定是从dp[j-i]这个状态转移过来的。那么只需要减去dp[j-i]即可。
    对于本题,若操作为向集合里添加某个数,那么只需要从k到x遍历一遍dp,然后转移方程为dp[i]=dp[i-x]+dp[i];若在集合里删除某个数,那么只需要从x到k遍历一遍dp,然后转移方程为dp[i]=dp[i]-dp[i-x]。

难点
这个题真正值得关注的是如何理解遍历顺序(添加为倒序遍历,删除为正序遍历):

  • 若添加某个数,那么可以类比01背包,你只是增加了一个x,dp[i]的转移只是比原来多了一种路径(dp[i-x]+x),所以只需要将原来的dp[i-x]再加上一次就可以了,这也是保证了dp的无后效性,所以需要从后向前遍历。(如果你正向遍历,你就会多加很多次你添加的x,然后只多添加了一个x)
  • 若删除某个数,那么此时就要考虑到前面的数的方案数对后面数的方案数的后效性了,因为你设想还是倒序遍历,当你更新dp[i]=dp[i]-dp[i-x]时,此时的i-x若仍然大于x,那么dp[i-x]也要发生变化,也就是先更新小的,再更新大的。(好好理解这两个遍历顺序)

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
const int maxn=2e5+10;
int dp[maxn];

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	
	int q,k;
	cin>>q>>k;
	dp[0]=1;
	while(q--)
	{
		char s;
		int x;
		cin>>s>>x;
		if(s=='+')
		{
			for(int i=k;i>=x;i--)
			  dp[i]=(dp[i]+dp[i-x])%mod;
		}
		else 
		{
			for(int i=x;i<=k;i++)
			  dp[i]=(dp[i]-dp[i-x]+mod)%mod;
		}
		cout<<dp[k]%mod<<endl;
	}
	
	
	
	
	return 0;
}

标签:subset,遍历,int,sum,那么,cin,ABC,添加,dp
From: https://www.cnblogs.com/lulu7/p/18246227

相关文章

  • AT_abc335_d [ABC335D] Loong and Takahashi 题解
    题目传送门题目大意:高桥在一个地图的中心,有一条龙从地图的左上角开始,每次只能到达与他相邻的四个点,现给出地图的边长,请你给出一种方案,使得地图上的每个点除高桥所在的地方外,都被龙走过且不重复。解题思路:首先,我们拿到这个题目,想十秒,便会发现,我们按照螺旋矩阵的方式行走,......
  • bash中$'abc'用法
    在shell脚本或命令行中,$'abc'并不是一个标准的字符串表示方法。通常,shell中的字符串可以用单引号('abc')或双引号("abc")来定义。然而,$'...'这种语法在某些shell环境(如bash)中确实存在,并且它用于处理带有转义字符的字符串。这种语法允许你在字符串中使用特定的转义序列,例如\n......
  • ABC357
    Alink循环加每一个数,加到哪个数不能加了输出前一个数,注意如果加到最后还能加,记得输出\(n\)。点击查看代码#include<bits/stdc++.h>usingnamespacestd;intn,m;inth[105],sum;signedmain(){ cin>>n>>m; for(inti=1;i<=n;++i) cin>>h[i]; for......
  • CEC2013(python):六种算法(ABC、PSO、CSO、OOA、DBO、RFO)求解CEC2013
    一、六种算法简介1、人工蜂群算法(ArtificialBeeColonyAlgorithm,ABC)2、粒子群优化算法PSO3、鸡群优化算法CSO4、鱼鹰优化算法OOA5、蜣螂优化算法DBO6、红狐优化算法RFO二、6种算法求解CEC2013(1)CEC2013简介参考文献:[1]LiangJJ, QuBY, SuganthanPN......
  • 1. Two Sum Go实现
    在数组中找到2个数之和等于给定值的数字,结果返回2个数字在数组中的下标。1.解法1时间复杂度O(n^2)直接两次遍历所有节点,进行求和比较代码如下:functwoSum(nums[]int,targetint)[]int{ res:=make([]int,2,2) fori:=0;i<len(nums);i++{ forj:=i+1;j<len......
  • ABC 320F Fuel Round Trip
    题意在坐标轴上给定N个点,坐标依次为x1,x2,...,xn,你需要从原点前往xn并且实现往返,其中从第一个点到第N-1个点上有加油站,其中第i个加油站可以花费p[i]购买f[i]升汽油,汽油的上限为H升,每行驶一单位距离需要花费一升汽油。在全部过程中每个加油站最多使用一次,判断是否可以完成行程并......
  • C. Minimizing the Sum
    原题链接题解1.任何一个数,只能覆盖一次2.把被覆盖的数字具象化,那么最终数组一定是由若干个有颜色的区间(被覆盖)和无颜色区间(没有被覆盖)组成3.这里就是状态的巧妙之处了,已知我们要求\(n\)个数里最多\(k\)个数被覆盖的最小和,那么这\(k\)个数里,一定存在末尾连续\(j\)个数......
  • 「杂题乱刷」AT_abc154_e
    代码恢复训练2024.6.10.(补)链接(luogu)链接(atcoder)数位dp板子题。dfs(last,sum,_1)剩下未搜的数位数,当前非零数位数,目前是否取满。这里采用记搜的写法。点击查看代码/*Tips:你数组开小了吗?你MLE了吗?你觉得是贪心,是不是该想想dp?一个小时没调出来,是不是该考虑换......
  • 「杂题乱刷」AT_abc132_e
    代码恢复训练2024.6.11.链接(luogu)链接(atcoder)分层图板子。结束。代码:点击查看代码/*Tips:你数组开小了吗?你MLE了吗?你觉得是贪心,是不是该想想dp?一个小时没调出来,是不是该考虑换题?打cf不要用umap!!!记住,rating是身外之物。该冲正解时冲正解!Problem:算......
  • Summary:《Adversarial Machine Learning in Image Classification: A Survey Towards
    Note“TaxonomyofAdversarialImages”(Machado等,2023,p.5)(pdf)扰动范围(PerturbationScope):个体扰动(Individual-scopedperturbations):为每个输入图像单独生成的扰动。通用扰动(Universal-scopedperturbations):独立于任何输入样本生成的扰动,可应用于任何合......