证明:每次循环执行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。
相关推荐
苏言の狗5 分钟前
小R的并集大小期望计算 | 蛮力
数据结构·算法
BineHello11 分钟前
MPC用优化求解器 - 解决无人机轨迹跟踪
算法·矩阵·自动驾驶·动态规划·无人机
誓约酱14 分钟前
(每日一题) 力扣 14 最长公共前缀
算法·leetcode·职场和发展
冠位观测者1 小时前
【Leetcode 每日一题 - 补卡】2070. 每一个查询的最大美丽值
数据结构·算法·leetcode
誓约酱1 小时前
(每日一题) 力扣 860 柠檬水找零
linux·c语言·c++·算法·leetcode·职场和发展
地平线开发者1 小时前
手把手基于 MINI 数据集带你做一次板端精度评估
算法·自动驾驶
詹天佐1 小时前
ICCE 数字车钥匙介绍
人工智能·算法
ak啊1 小时前
记忆化(Memoization)
算法
moonless02222 小时前
【Python】你还不了解数据结构与算法?
数据结构·算法·编程语言
z_y_j2299704382 小时前
L1-039 古风排版
c语言·数据结构·算法