「闲话随笔」枚举子集与枚举子集的子集与枚举子集的子集的子集

「闲话随笔」套娃子集

点击查看目录

为什么要写这么弱智的内容:我太菜了。

枚举子集作用

常用于状压 DP。

枚举一个状态的所有子集状态。

例如 1101 的子集有:

1101
1100
1001
1000
0101
0100
0001
0000

代码

for (ll i = u; i; i = (i - 1) & u) {
	// i 是子集
}

原理

每次 i-1 后都会把当前状态的最后一个 1 后面的所有位变为 1,这一位变为 0

&u 将不能为 1 的每一位变为零,保证当前枚举的是子集。

那么当前就可以枚举到 比上一个状态小的所有状态中最大的状态

例如枚举 1101 的子集,当前到了 1100

进行第一步得 1011,进行第二步得 1001

感觉讲了和没讲一样,感性理解吧。

复杂度

枚举一个状态的的复杂度显然是 2n 的,这里主要讨论枚举 02n 的所有状态的所有子集的时间复杂度。

显然可得式子:

i=0n(ni)2i

发现很眼熟,用个谔项式定理套一下:

i=0n(ni)2i=i=0n(ni)2i1ni=(2+1)n=3n

得到了时间复杂度 Θ(3n)

意义?

每一位有三种可能:

  • 当前枚举的子集和状态这一位都是 0
  • 当前枚举的子集和状态这一位都是 1
  • 当前枚举的状态的这一位是 1,但它的子集的这一位是 0

乘法原理得 3n

套娃子集

其实刚才讨论的情况可以当成:枚举状态 2n 的子集的子集。

那么我们考虑套娃:

2nk

时间复杂度:

i1=0n(ni1)i2=0n(ni2)ik=0n(nik)1=i1=0n(ni1)i2=0n(ni2)ik1=0n(nik1)2n=i1=0n(ni1)(k1)n=kn

组合意义同上。

真是非常有趣的性质呢。

The End

本文作者:K8He

本文链接:https://www.cnblogs.com/K8He/p/chat_20221001.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   K8He  阅读(164)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起