個ある何かの0個以上から成る集合
を
ビットの整数で表すことにする。
このとき、集合に含まれる要素が個なら全部で
ビット立っている 。
(__builtin_popcount(S) == k
)
この集合の部分集合
をすべて列挙しようとすると、空集合も含め
通りある。
集合Sとしてありうる全てのパターンについてこれを列挙することを考えると、
個から
個選ぶ組み合わせが
通りで、そのそれぞれについて
通りの部分集合があるので全部で
通りについて考えることになる。
ここで驚くべきことは、任意の非負整数について
$$ \sum_{k=0}^{n}{_nC_k\cdot2^k}=3^n $$
が成り立つということである。
各ビットについて
でも
でも立っている
でのみ立っている
でも
でも立っていない
の3通りの状態がありうるのだから自明ではある。
bitDP回りでよくという数が出てくるのはそのためである。
実際の回し方については
ビットによる部分集合の列挙 - SRM diary(Sigmar) - TopCoder部
の解説がわかりやすい。
意地悪な制約の問題では計算量 では間に合わず、
に下げる工夫が求められたりする。
高速ゼータ変換/高速メビウス変換 - naoya_t@hatenablog
の出番である。