SOS DP
SOS DP
简介
全称 Sum Over Subset DP,用于在 \(O(2^n \times n)\) 的复杂度内解决子集和问题。
算法原理
定义 \(dp_{k,mask}\) 表示只考虑二进制下从低到高前 \(k\) 位时,\(mask\) 的所有子集权值之和。
转移分类讨论:
-
\(mask\) 第 \(k\) 位为 \(0\),子集第 \(k\) 位也只能是 \(0\),显然直接继承,\(dp_{k+1,mask}=dp_{k,mask}\)。
-
\(mask\) 第 \(k\) 位为 \(1\),子集第 \(k\) 位可选或不选,有转移:\(dp_{k+1,mask}=dp_{k,mask}+dp_{k,mask \oplus 2^k}\)
答案是 \(\sum dp_{n,mask}\),初始 \(dp_{0,mask}=a_i\)。这个显然可以滚动掉一维。
例题
- CF165E(转化为子集问题)
我们发现,若两个元素的按位与之后为 \(0\),则它们的 \(1\) 和 \(0\) 必须错开。
考虑对于其中一个取反,则它必须是另一个的子集。
直接 SOS dp,每次 \(dp_{mask}\) 继承 \(dp_{mask \oplus 2^i}\) 即可,初始 \(dp_{a_i}=a_i\),答案为 \(dp_{(2^n-1) \oplus a_i}\)。
- ARC100C(SOS dp 维护最值、约束条件的转化)
这个 \(\le\) 不好考虑,转化为 \(=\)。设 \(dp_{k}\) 表示按位或恰好为 \(k\) 的最大值。
显然若 \(i \operatorname{or} j=k\),则 \(i,j\) 都是 \(k\) 的子集,直接 SOS dp 转移。
如何转回 \(\le\)?询问时维护前缀最大值即可。
- CF449D(容斥原理、反演思想)
不难发现若要使得 \(a_{i_k}\) 按位与之后要为 \(0\),则 \(a_{i_k}\) 某一位上不能全为 \(1\)。
这个约束可以进行转化,我们发现超集(包含某个集合的集合)是一个更宽松的限制,考虑对超集进行 dp。
与 SOS dp 类似的,我们考虑设计 \(dp_{mask}\) 为 \(mask\) 的超集的组数,但这个东西并不好转移。
进一步观察,我们发现只有包含 \(mask\) 中所有 \(1\) 的 \(a_i\) 才能参与超集(超集也是由 \(a_i\) 组成的),于是设计辅助状态 \(cnt_{mask}\) 表示包含 \(mask\) 所有 \(1\) 的 \(a_i\) 个数,显然有 \(dp_{mask} = 2^{cnt_{mask}}-1\)(每个 \(a_i\) 可以选或者不选,不能为空)。
这个东西显然 \(mask\) 中的 \(1\) 越少,\(cnt\) 就越大,考虑从大到小转移,有 \(dp_{mask} \leftarrow dp_{mask \operatorname{or} 2^i}\)。
以上这部分是超集和 dp 的一般思路。
答案如何求?显然我们需要 \(dp_{0 \sim 2^{m}-1}\) 的并集(不全为 \(1\)),于是容斥一下即可,每一项乘上对应的容斥系数。
- CF1234F(观察性质)
不难观察到两个性质:
-
字符集大小仅为 \(20\),表明答案不超过 \(20\)
-
两个满足题意的子串不会重叠
这样问题转化为求取合法的字符集,考虑 SOS dp。
考虑枚举每个结尾的位置然后向前寻找最大的合法子串来记录 dp 初始状态,转移就是维护最大值,最后枚举合法状态并求出其子集,两个答案进行拼接取 \(\max\) 即为答案。
- ABC349F(从特殊入手、观察性质)
我们先考虑特殊情况,对于 \(a_i \nmid M\),显然 \(lcm\) 不会等于 \(M\),可以舍弃。
进一步的,想到了整除,显然我们可以将 \(M\) 质因数分解。对于质因子 \(q_j ^{c_j}\),\(a_i\) 必须被它整除才能使 \(lcm\) 等于 \(M\),这个似乎可以用二进制状态表示。由于 \(13\) 个不同质因子相乘就已经达到 \(10^{16}\) 了,这印证了我们的想法。
有了这个思考,我们考虑向 SOS dp 转化。我们发现 \(\operatorname{lcm}\{a_i\}=M\),等价于 \(a_i\) 的二进制状态按位与之后得到全集。我们成功将此题转化为了 SOS dp,直接设计辅助状态 \(cnt\) 然后 dp 求取,最后子集反演即可得到答案。
- Codechef-covering(正变换与逆变换的结合)
首先我们要求的就是 $$\sum_{X} \sum_{X \subset A,B,C} F_A G_B H_C$$
交换求和顺序得 $$\sum_{A,B,C} F_A G_B H_C \sum_{X \subset A,B,C} 1 $$
后面的部分化简得 $$\sum_{A,B,C} F_A G_B H_C 2^{\mid A \cup B \cup C \mid}$$
这个东西不好直接求,考虑反演。
令 \(F'_{S} = \sum_{A \subset S} F_{A},G'_{S} = \sum_{B \subset S} G_{B},H'_{S} = \sum_{C \subset S} H_{C}\),这个可以正向 SOS dp 求得。
令 \(W_{S} = F'_{S} G'_{S} H'_{S}\),再做一遍逆向的 SOS dp 即可得到原答案。
总结
-
可以使用位运算对题目进行初步转化
-
直接做不好做时,考虑放宽约束然后容斥解决。
-
也可以使用反演(正变换与逆变换结合)来简化问题。
浙公网安备 33010602011771号