目次

GAMEFREAK Programming Contest 2023 (AtCoder Beginner Contest 317) F,G問題メモ

GAMEFREAK Programming Contest 2023 (AtCoder Beginner Contest 317)

抽選でポストカードが貰える!

F - Nim

F - Nim

問題

解法

3数の排他的論理和が0なので、2進数で表したときに全ての桁についてbitが「2数でだけ立ってる」か「どれも立ってない」かである。

$A_i$ の制約が小さいので、あまりを持った桁DPができる。
3数同時にあまりを管理しても、$O(\log{N} A_{max}^3)$ で、$6 \times 10^4$ 程度に収まる。
次の桁にbitを3つ中2つだけ立てた場合、どれにも立てなかった場合、に遷移していき、最終的にあまりが全て0のパターン数が答え、という解法が取れそう。

$N$ 以下であることが求められるので、よくある桁DPなら

みたいな方法を取るが今回は3数同時に面倒を見る必要があり、どれか1個だけが $N$ ちょうどとかいう場合も考慮するので、 $N$ ちょうども状態の中に混ぜ込む必要がある。

$N$ を2進数で表して上から $k$ 桁を取ったものを $f(k)$ とするとして、

(例)N = 43 = 101011(2)  ⇒  f(4) = 1010(2) = 10

以下のDPを定義する。

$DP[0,A_1,A_2,A_3]=1$ からはじめて、 $N$ を超えないように、また $N$ ちょうどの状態に注意しながら、 3数のうち2個にビットを立てるか、どれにも立てないかでパターンを遷移させていく。

最終的に $DP[N,0,0,0]$ が答えだが、$N$ 自身が $A_1$ で割りきれる場合、$DP[N,A_1,0,0]$ も答えに加算する。
(もし $A_2,A_3$ も割り切れるなら、その組み合わせだけ参照箇所が増える)

最後に、答えには $X_i=0$ の場合も含まれてしまっている。1以上で無ければいけないので、これを除外する。

以上で答えとなる。

Python3

G - Rearranging

G - Rearranging

問題

解法

全てを一度に決めようとすると上手くいかない。

実は、「$1~N$ の数字が $M$ 個ずつ配置されている」という条件を満たしていれば必ず可能であり、 その証明があれば、1列ずつ貪欲に決めていってもいい、という考え方となる。
(入力サンプルにも可能な例しか無かった時点で少し怪しかったね)

いま、一番左端の1列だけをとりあえず決めるとする。
どうやっても $1~N$ を揃えるのは不可能というのはどんな状態か?

二部マッチングにおけるホールの定理を利用すれば、

場合に不可能であり、そうでなければ何らかの完全マッチングは存在する、ということになる。

→ 3 3 3 3 5    4行に存在する数の種類が、あわせても3種類しかない
→ 3 3 5 5 6    みたいな行の集合がある場合に不可能となる
   o o o o o
→ 3 3 3 6 6
→ 5 5 6 6 6

だが、これは少し考えると、数のどれかが $M$ 個より多く存在していないと不可能なので、あり得ない。

よって、左端の列に $1~N$ は必ず揃えることができ、1つ列が減った状態に帰結できる。
1つ列が減った状態も、$N$ 行 $m$ 列に対して「$1~N$ が $m$ 個ずつ」という条件は満たされているので、 同じ理屈により再帰的に完全マッチングが存在することが証明できる。

完全マッチングは最大流で求められる。
$N,M$ の制約が小さいので、各行に残っている数を管理しながら $M$ 回、グラフ構築から最大流を流しても十分間に合う。

Python3