枚举子集

状压 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\) 去掉。

posted @ 2025-06-14 14:32  MinimumSpanningTree  阅读(5)  评论(0)    收藏  举报