对于二进制状态 SSS,可以用此方法不重不漏地枚举出子状态:
for (int sub = S; sub; sub = (sub - 1) & S) {
// sub 为 S 的子集
}
【证明】 由 sub=(sub−1)∩Ssub = (sub - 1) \cap Ssub=(sub−1)∩S 可知 subsubsub 每次必然会变小,于是我们只需要证明区间 ((sub−1)∩S,sub)\left((sub - 1) \cap S, sub\right)((sub−1)∩S,sub) 中不存在 SSS 的子集。设 sub=(d1d2⋯dk10⋯0)2sub = (d_1d_2 \cdots d_k 10 \cdots 0)_2sub=(d1d2⋯dk10⋯0)2,那么 sub−1=(d1d2⋯dk01⋯1)2sub - 1 = (d_1d_2 \cdots d_k 01 \cdots 1)_2sub−1=(d1d2⋯dk01⋯1)2,由于 subsubsub 是 SSS 的子集,则 (d1d2⋯dk00⋯0)2(d_1d_2 \cdots d_k 00 \cdots 0)_2(d1d2⋯dk00⋯0)2 是 SSS 的子集,因此考虑 (d1d2⋯dk01⋯1)2∩S(d_1d_2 \cdots d_k 01 \cdots 1)_2 \cap S(d1d2⋯dk01⋯1)2∩S,得到的一定是 ((d1d2⋯dk00⋯0)2,(d1d2⋯dk10⋯0)2)\left((d_1d_2 \cdots d_k 00 \cdots 0)_2, (d_1d_2 \cdots d_k 10 \cdots 0)_2\right)((d1d2⋯dk00⋯0)2,(d1d2⋯dk10⋯0)2) 中值最大的子集,问题得证。
【时间复杂度】 枚举单个状态的子集复杂度为 O(2m)O(2^m)O(2m)(mmm 为 SSS 中 111 的个数)。考虑枚举全集 2n−12^n - 12n−1 的每个子集的子集的时间复杂度:O(∑i=0n(Cni⋅2i))=O((1+2)n)=O(3n)O\left(\sum\limits_{i = 0}^{n} \left(C_{n}^{i} \cdot 2^i\right)\right) = O\left((1 + 2) ^ n\right) = O(3^n)O(i=0∑n(Cni⋅2i))=O((1+2)n)=O(3n)(二项式定理:(1+x)n=∑i=0n(Cni⋅xi)(1+x)^n = \sum\limits_{i = 0}^{n} \left(C_{n}^{i} \cdot x^i\right)(1+x)n=i=0∑n(Cni⋅xi))。