枚举子集
状压 dp 的一个小技巧。
这是代码:
for(int j=i;j;j=(j-1)&i)
其中,\(i\) 是枚举的集合,\(j\) 是子集。但是要注意这个办法没有枚举空集,需要自行处理。
考虑证明。我们分三步,分别证明正确性、不重、不漏。
-
正确性:由于这个
j=(j-1)&i,所以 \(j\) 不可能出现除 \(i\) 有以外的位。 -
不重:由于
j=(j-1)&i所以 \(j\) 是严格递减的,不会重。 -
不漏:由于 \(j-1\) 等价于删去在二进制下 \(j\) 的最右的一个 \(1\),并将这位后面的二进制位变为 \(1\),又因为进行了
&i,所以可以把多的 \(1\) 去掉。

浙公网安备 33010602011771号