〈説明用メモ〉O(3^N)について本気出して考えてみた
個ある何かの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
の出番である。