「闲话随笔」枚举子集与枚举子集的子集与枚举子集的子集的子集
1.「闲话随笔」枚举子集与枚举子集的子集与枚举子集的子集的子集
「闲话随笔」套娃子集
为什么要写这么弱智的内容:我太菜了。
枚举子集作用
常用于状压 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
。
感觉讲了和没讲一样,感性理解吧。
复杂度
枚举一个状态的的复杂度显然是 的,这里主要讨论枚举 的所有状态的所有子集的时间复杂度。
显然可得式子:
发现很眼熟,用个谔项式定理套一下:
得到了时间复杂度 。
意义?
每一位有三种可能:
- 当前枚举的子集和状态这一位都是
0
; - 当前枚举的子集和状态这一位都是
1
; - 当前枚举的状态的这一位是
1
,但它的子集的这一位是0
。
乘法原理得 。
套娃子集
其实刚才讨论的情况可以当成:枚举状态 的子集的子集。
那么我们考虑套娃:
时间复杂度:
组合意义同上。
真是非常有趣的性质呢。
本文作者:K8He
本文链接:https://www.cnblogs.com/K8He/p/chat_20221001.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步