D - Polyomino 解説
by
Kiri8128
ビット演算による実装
この 問題 の 解説 の方法と同様、盤面を 2 進法で表された整数だと考えて処理すると、実装が簡単になり、並列計算の分だけ計算量も小さくなります。
本問では、前回の問題に比べ回転があるところの処理が難しくなっています。 公式解説 のように \(2\) 次元配列としてしても良いですが、並列計算を生かす方法もあります。具体的には、例えば、横向きのときは \(2\) 進法、縦向きのときは \(32\) 進法と思って入力を変換すると良いです。
(方針)
- \(2\) 進法で考えます
- 右端に番兵を \(1\) マスずつ付けて、盤面を横 \(5\) マス、縦 \(4\) マスの \(20\) マスを並べたひとつの \(20\) ビットの整数で表現することを考えます
- 入力を回転させる必要があるので、受け取った直後に \(2\) 進法・ \(32\) 進法で変換します
- 上下・左右を含む平行移動はすべてビットシフトで表現できます
- 入力(を回転させたもの)の末尾の \(0\) を消した状態から、最大で \(18\) ビット左シフトすれば十分です
a
の末尾の \(0\) を消したものはa // (a & -a)
で計算できます- 全体を覆っていることは、盤面が \(507375\) (\(=1+2+2^{2}+2^{3}+2^{5}+2^{6}+2^{7}+2^{8}+2^{10}+2^{11}+2^{12}+2^{13}+2^{15}+2^{16}+2^{17}+2^{18}\))と一致することを確認すれば良いです
- \(2\) つが「重ならない」は、例えば
a & b == 0
で表現できます(popcount で確認する方法もあります)
AC コード (PyPy3)
投稿日時:
最終更新: