证明:每次循环执行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。
相关推荐
songx_9926 分钟前
leetcode10(跳跃游戏 II)
数据结构·算法·leetcode
先做个垃圾出来………1 小时前
差分数组(Difference Array)
java·数据结构·算法
hansang_IR2 小时前
【题解】洛谷 P4286 [SHOI2008] 安全的航线 [递归分治]
c++·数学·算法·dfs·题解·向量·点积
乐迪信息2 小时前
乐迪信息:AI摄像机在智慧煤矿人员安全与行为识别中的技术应用
大数据·人工智能·算法·安全·视觉检测
多恩Stone2 小时前
【3DV 进阶-2】Hunyuan3D2.1 训练代码详细理解下-数据读取流程
人工智能·python·算法·3d·aigc
惯导马工3 小时前
【论文导读】IDOL: Inertial Deep Orientation-Estimation and Localization
深度学习·算法
老姜洛克3 小时前
自然语言处理(NLP)之n-gram从原理到实战
算法·nlp
CoovallyAIHub4 小时前
基于YOLO集成模型的无人机多光谱风电部件缺陷检测
深度学习·算法·计算机视觉
CoovallyAIHub4 小时前
几十个像素的小目标,为何难倒无人机?LCW-YOLO让无人机小目标检测不再卡顿
深度学习·算法·计算机视觉
怀旧,4 小时前
【C++】19. 封装红⿊树实现set和map
linux·c++·算法