境界の状態
現在の列より左側のマスがすべて埋まっている状態を考える。横向きの直線形トロミノの長さは なので、既に置いたタイルが残るのは現在の列と次の列だけである。この四マスをビットマスクで表し、ビット を現在の列の上下、ビット を次の列の上下に対応させる。
現在の列の最初の空きマスを覆うタイルを置く。列が埋まったらマスクを二ビット右にずらす。常に最初の空きマスを選べば、同じ敷き詰め方を置く順番の違いで重複して数えない。マスク から始め、 列を処理した後にマスク となる場合だけを答えに含める。
到達可能なマスクは である。上下対称のマスクの個数は等しい。 列を処理した時点で、 をそれぞれマスク の個数とする。マスク と 、 と 、 と の個数はそれぞれ等しい。
対称な二つの合計ではなく、一つのマスクの個数を保持する。最初の空きマスを覆う配置を列挙すると、次の遷移が得られる。
線形 DP と行列累乗
遷移を 回行えば 時間、 空間で計算でき、サブタスク 2 を通過する。全体の制約では六つの値を列ベクトルとし、 と書く。ただし
繰り返し二乗法で を計算すると、時間計算量は 、空間計算量は となる。すべての計算を を法として行う。
付属コードの漸化式
遷移行列は
を満たす。したがって に対して
が成り立つ。初期値は
である。
線形解法はこの漸化式を順に計算する。正解コードは状態 の コンパニオン行列を累乗する。係数 は法から を引いた値で表し、指数には ビット整数を使う。
サブタスク 1 では全 マスをビットマスクで表し、最初の空きマスを覆うすべてのタイルを試して、占有マスクごとの答えをメモ化する。左から順に埋めるため未完成の状態は境界付近の二列だけに限られ、各列の状態数は定数個である。最初の空きマスを線形探索する実装は 時間、 個の保存状態を使う。付属の naive は盤面全体を最大 ビットで表す独立した実装である。
直線形と L 字形の両方を数える必要がある。縦向きの直線形トロミノは高さが なので入らない。空の盤面の個数 は初期値としてのみ使い、入力で は与えられない。
各積和の直後に剰余を取れば、中間値は 以下であり、符号付き ビット整数で十分である。
Solution written by GPT