【强基】SOS DP(子集 DP)

Part 1:前置知识

1、状压 DP

2、基本的位运算操作

Part 2:SOS DP

(以下的内容大部分翻译至CF上的原文

1、例题引入

给定一个含 2 N 2^N 2N 个整数的集合 A A A,我们需要计算: ∀ x ⊆ A \forall x \subseteq A xA x x x 中所有元素 i i i A [ i ] A[i] A[i] 的和,即求:
F [ m a s k ] = ∑ i ⊆ m a s k A [ i ] F[mask]=\sum\limits_{i \subseteq mask}^{}{A[i}] F[mask]=imaskA[i]

2、解题思路

法一:暴力枚举
  • 我们可以枚举每一个 m a s k mask mask,再枚举集合中的所有元素 i i i,判断 i i i 是属于集合 m a s k mask mask。这样做的时间复杂度为 O ( 4 N ) O(4^N) O(4N)

  • 代码

for(int mask=0; mask<(1<<N); mask++)
  	for(int i=0; i<(1<<N); i++)
		if((mask&i)==i)
		  	F[mask]+=A[i];
法二:枚举子集
  • 对于任意 m a s k mask mask,如果它做的二进制位上有 k k k 1 1 1,那么它就有 2 k 2^k 2k 个子集,我们只需遍历这些子集便可。
    时间复杂度为 O ( ∑ k = 0 N ( N k ) 2 k ) = O ( ( 1 + 2 ) N ) = O ( 3 N ) O(\sum\limits_{k=0}^{N}{\tbinom{N}{k}2^k})=O((1+2)^N)=O(3^N)

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值