CF2030E 简记
CF2030E
题目描述
假设我们将数组 \(b\) 的元素划分为任意数量 \(k\) 个非空多重集 \(S_1, S_2, \ldots, S_k\),其中 \(k\) 是任意正整数。定义 \(b\) 的得分为所有可能划分下 \(\operatorname{MEX}(S_1) + \operatorname{MEX}(S_2) + \ldots + \operatorname{MEX}(S_k)\) 的最大值。
给你一个长度为 \(n\) 的数组 \(a\)。由于他知道你计算 \(a\) 的得分太容易了,因此他要求你计算 \(a\) 的所有 \(2^n - 1\) 个非空子序列的得分之和。由于答案可能很大,请你输出其对 \(998\,244\,353\) 取模的结果。
做法:
先考虑一个集合怎么划分才能使得 \(\operatorname{MEX}\) 的和最大。
假设:各个数字的数量如下:
| \(0\) | \(1\) | \(2\) | \(3\) | \(4\) |
|---|---|---|---|---|
| \(3\) | \(4\) | \(1\) | \(2\) | \(2\) |
那么,能产生贡献的最优划分如下:
\([0,1,2,3,4,5]\)
\([0,1,2]\)
\([0,1]\)
所以,一个集合能划分出的 \(MEX\) 的最大和就是:
其中 \(C_i\) 表示数 \(i\) 出现的次数。
这一步并不难发现。
但关键是题目需要求出所有子序列的权值和。
考虑子序列的几种做题方法:
-
贡献法
-
极值类:枚举最大值最小值是谁
-
按位拆贡献
-
\(DP\) :处理增量
-
...
此处增量和贡献是不好求的,这是因为与答案有关的是某一种数的个数,而并非某一个数的贡献。
所以有一个大概的思路就是:
按照数的大小顺序处理,由于答案与前缀最小出现次数有关,所以设 \(dp[i][j]\) 表示前 \(i\) 个数,最小出现次数是 \(j\) 的子序列个数。
转移大致如下:
设 \(S(c,j)=\sum_{k=j}^{n}\binom{c}{j}\) ,即这种颜色至少选了 \(j\) 个的方案数。
注意 \(j\) 只枚举到 \(\min (cnt[i],mn)\) 。\(mn\) 表示前缀最小出现次数。
当前前缀产生的贡献:
设 \(precnt=\sum_{j=0}^{i}cnt[j]\) ,则:
原因是最小出现次数为 \(j\) 则每个子序列在这一轮对答案产生 \(j\) 的贡献(对应的是 \(\min_{j\le i}C_j\) )。
而这样子序列的个数是 \(dp[i][j]\times 2^{n-precnt}\) ,原因是后面的数字可以随便选。
由于 \(j\) 最多只会枚举到 \(cnt[i]\) ,所以整体是 \(O(n)\) 的。
用滚动数组优化后可以做到空间时间都是:

浙公网安备 33010602011771号