二进制

枚举子集

复杂度 \(O(子集个数)\)

for (int i = S; i != 0; i = (i - 1) & S) ;

首先& S可以保证一定是子集

怎么证明一定全部会枚举到呢?

因为\(-1\)会将最小的\(1\)位变成\(0\), 更小的位全部变成\(1\), 因为是最小的\(1\), 所以接下来第一个 十进制数值 更小的子集肯定这一位是\(0\)了, 这样就可以调到接下来那个子集

枚举子集的子集

复杂度 \(O(3 ^ n)\)

for (S in ((1 << n) - 1))
{
    for (T in S)
    {
        ...
    }
}

直观可以得到一个较松的上界 \(O(4 ^ n)\)
其实对于一个 1 元素有 \(x\) 个的集合, 他的子集有 \(2 ^ x\) 个, 而这样大小为 \(x\) 的集合是 \(\binom{n}{x}\)
容易得到:

\[\sum_{x} \binom{n}{x} \cdot 2 ^ x \]

由二项式定理

\[(1 + x) ^ n = \sum_{i} \binom{n}{i} \cdot x ^ i \]

可得

在上式中带入 \(x = 2\), 结果 \(= (1 + 2) ^ n = 3 ^ n\)

posted @ 2019-11-14 14:53  Kuonji  阅读(108)  评论(0编辑  收藏  举报
nmdp