D - Hanjo Editorial
by
ngtkana
問題文中の \(H, W, A, B\) を小文字で \(h, w, a, b\) とも表すことにします。
まず \(n = h w\) とおいて、マスに横書き文章スタイルで \(0, \dots, n - 1\) と付番しておきましょう。マスの集合 \(S\) に対して \(\mathtt { dp } [ S ]\) を、その範囲に長い畳を、はみ出さないように満遍なくちょうど敷き詰める場合の数であるとしましょう。このときすべての \(2 a\) 元集合に関する \(\mathtt { dp } [ S ]\) の和
\[ \sum _ { S \in \binom { [ n ] } { 2 a } } \mathtt { dp } [ S ] \]
が答えです。
さてこの \(\mathtt { dp } [ S ]\) をどうやって求めるかなのですが、まず明らかに \(\mathtt { dp } [ \emptyset ]\) は \(1\) です。遷移は、空いている場所に畳を置けばよいです。bit DP でいうと、このような形の遷移を適切な順序で書いていくことになるかと思います。
dp [ x | 1 << i * w + j | 1 << ( i + 1 ) * w + j ] += dp [ x ]
dp [ x | 1 << i * w + j | 1 << i * w + ( j + 1 ) ] += dp [ x ]
ただし、
- すでにおいているところに畳を置かないように、
- そして場所 \(p\) と場所 \(q\) に一枚ずつ畳を置くときに、\(p, q\) の順番で置くのと \(q, p\) の順番で置くのをダブルカウントしてしまわないように
注意しましょう。1 つめは bitwise and をするとよいです。2 つめは、もともとの x よりも、今から畳を置く場所の集合 (1 << i * w + j | 1 << ( i + 1 ) * w + j や 1 << i * w + j | 1 << i * w + ( j + 1 ) のことです。)のほうが整数として大きいことを課せばよいです。
結局、小問題の個数(DP の状態数)が \(2 ^ N\)、遷移の個数が \(\Theta ( N )\) であり、遷移のひとつひとつが定数時間ですから、全体で \(\Theta \left ( 2 ^ N N \right )\) (ただし \(N = H W\))となります。
参考提出(Rust, 16 ms):https://atcoder.jp/contests/abc196/submissions/21164141
posted:
last update:
