🦄

AtCoder Regular Contest 143 C 解答までの流れと嘘解法

2022/07/02に公開

競技プログラミングの精進として、AtCoder Regular Contest(ARC) 143 C問題、
Piles of Pebblesを解きました。全テストケース正解(AC)になるまでに考えたことと、
その途中で見つけた嘘解法を紹介します。

問題

下記のページからの引用です。

小石の山が N 個あります.最初,i 番目の山には A_i個の小石があります.

これらを用いて,高橋君と青木君がゲームをします. 高橋君から始めて,交互に次の操作を行い,操作を行えなくなった方が負けとなります.

山を 1 つ以上選び,選んだそれぞれの山から,高橋君の操作の場合は X 個ずつ,青木君の操作の場合は Y 個ずつ小石を取り除く. ただし,小石の個数が足りない山を選ぶことはできない.
二人が最適に行動したとき,どちらがゲームに勝つかを求めてください.

https://atcoder.jp/contests/arc143/tasks/arc143_c

値をシンプルにして二人の最適な行動を考える

A_i(1\le i\le N)からX個、Y個ずつ石を取っていくのでA_iX+Yの倍数と考えてみました。

この状態であれば

  • 先手がいくつか山を選んでX個の石を取る
  • 後手が同じ山を選んでY個の石を取る

ということを繰り返せば、先手がどの山からも石が取れなくなり後手が必勝ということがわかりました。

A_iをより一般化する

上で考えたシンプルな例を基にA_iを一般化してみました。実際にはA_iX+Yで割った余りM_i(1\le i\le N, 0 \le M_i\lt X+Y)があります。

改めてM_i(1\le i\le N, 0\le M_i\lt X+Y)ですので

  • M_iから取れる最後の石を取った方が必勝
  • M_iからは先手、後手のどちらかしか石を取れないか、どちらも石を取れない

ここで何となく先手でM_iから石を取れなければ負け、1つ以上のM_iから石が取れれば勝ちそうな感触が掴めてきました。

嘘解法

上の感触をコード化してみましたら、、、ACになりました。
https://atcoder.jp/contests/arc143/submissions/32838230

でも少し引っかかる点がありましたので、もう少し考察してみました。
例えば、N=3, X=3, Y=2, A=\{8, 8, 8\}の場合は、下図のように先手が勝つ手がありますが、後手が勝つと判定されてしまいます。

# t1.txtは上記のテストケース
$ go run main.go < t1.txt
Second

改めて解法を提出

嘘解法はX\gt Yのケースについて、考察が不十分と考えられました。
例えば、先手がX個石を取った後、先手が石を取れなかった山にY個の石が残っている場合があります。

この考察を嘘解法でおかしかったケースも正しくなることも確認し、その他考慮漏れがないか
先手、後手それぞれどのような条件であれば勝てるかを整理しました。

XYの大小 先手 後手
X\le Y M_iから1つ以上の山から石が取れる 先手がM_iから石を取れない
X\gt Y M_iから1つ以上の山から石が取れ、後手が石を取れない 先手がM_iから石を取れない
もしくは
先手が石を取った後1つ以上の山から石が取れる

改めて提出してACになりました。
https://atcoder.jp/contests/arc143/submissions/32838700

最後に

今回は精進ですので、それなりの時間をかけて考察をしました。
途中、嘘解法がありましたものの、ARCの問題でACに辿りついたときときは
AtCoder Beginner Contest(ABC)とは違った達成感がありました。
これがコンテスト中にできると、さらにそういった感触が味わえたり、レートの飛躍もできるかなと思います。
残念ながら、私はARCでは中々レートアップすることができないため、
コンテスト時間中にひらめくことが個人的な課題と思います。

Discussion