证明:每次循环执行i = (i-1)&s可以枚举s表示集合的所有子集i

状态压缩:使用二进制数表示一个集合的情况,第i位为1表示第i元素在集合中,为0表示不在集合中。

已知i表示的集合是s表示的集合的子集,枚举s的所有子集i可以写为

cpp 复制代码
for(int i = s; i != 0; i = (i-1)&s){}

证明:每次循环执行i = (i-1)&s可以枚举s表示集合的所有子集i

使用数学归纳法:

  1. 证明:当s只有1位为1时,每次循环执行i = (i-1)&s可以枚举s表示集合的所有子集i
    s只有1位为1,设s为 2 n 2^n 2n,那么s = 10...(n个0)...0
    第一次循环开始,i为s,i = 10...(n个0)...0
    而后求i = (i-1)&s
    i-1 = 01...(n个1)...1
    (i-1)&s = 0...(n+1个0)...0
    即i = 0...(n+1个0)...0
    i已经取到了s的所有子集。
  2. 已知s有k位1时,每次循环执行i = (i-1)&s可以枚举s表示集合的所有子集i,证明:当s有k+1位1时,每次循环执行i = (i-1)&s可以枚举s表示集合的所有子集i。
    因为s有k+1位1,所以s的1的位数大于等于2。
    设s的形式为10...(a个0)...01X...X,X可以是1也可以是0。从第2个1开始,已知到右端共有k位1。当i中1的位数大于等于2时,在执行i = (i-1)&s后,最高位的1都不会变化,会变化的只有1X...X,也就是有k位1的部分。
    已知一个数有k位1时,每次循环执行i = (i-1)&s可以枚举它表示集合的所有子集,把对1X...X枚举到的每个子集加上最高位1表示的元素,就得到了s的包含最高位1表示的元素的所有子集。
    不断执行i = (i-1)&s枚举1X...X的所有子集后,1X...X会变为0, 即i=10...0。
    再次执行i = (i-1)&s,i = 0...(a+1个0)...1X...X,该数字包含k位1,每次循环执行i = (i-1)&s可以枚举它表示集合的所有子集,对1X...X枚举到的每个子集为s不包含最高位1表示的元素的所有子集。
    因此,当s有k+1位1时,每次循环执行i = (i-1)&s可以枚举s表示集合的所有子集i。
相关推荐
地平线开发者7 小时前
SparseDrive 模型导出与性能优化实战
算法·自动驾驶
董董灿是个攻城狮8 小时前
大模型连载2:初步认识 tokenizer 的过程
算法
地平线开发者8 小时前
地平线 VP 接口工程实践(一):hbVPRoiResize 接口功能、使用约束与典型问题总结
算法·自动驾驶
罗西的思考8 小时前
AI Agent框架探秘:拆解 OpenHands(10)--- Runtime
人工智能·算法·机器学习
HXhlx11 小时前
CART决策树基本原理
算法·机器学习
Wect12 小时前
LeetCode 210. 课程表 II 题解:Kahn算法+DFS 双解法精讲
前端·算法·typescript
颜酱13 小时前
单调队列:滑动窗口极值问题的最优解(通用模板版)
javascript·后端·算法
Gorway19 小时前
解析残差网络 (ResNet)
算法
拖拉斯旋风19 小时前
LeetCode 经典算法题解析:优先队列与广度优先搜索的巧妙应用
算法
Wect19 小时前
LeetCode 207. 课程表:两种解法(BFS+DFS)详细解析
前端·算法·typescript