Game Theory (HackerRank)
この記事は 解説 Advent Calendar 2017の24日目の記事です。
以下のコンテストの解説です。 www.hackerrank.com
はじめに
競プロ!!Advent Calendarのこの記事 (競プロにおけるNim、Grundy数とNimK - かっさのなにか)に 触発されて書きました(というか解いてないことを思い出した)。
以下ではNim, grundy数などの知識を前提としています。 全く知識がない、あるいは不安な方は上の記事を読んでから解く and/or 解説を読むことを推奨します。 またxorをで表します。 特に記述がなければ、先手(プレイヤー1)と後手(プレイヤー2)が交互に手を打つゲームとし、 どちらのプレイヤーが勝つか出力する問題と思ってください。
Game of Stones
概要
Programming Problems and Competitions :: HackerRank
山に石が個ある。 プレイヤーは山から個いずれかだけ取り除ける。 取り除くことができなくなったプレイヤーの負けである。
解法
メモ化再帰。
Tower Breakers
概要
Programming Problems and Competitions :: HackerRank
それぞれに石が個ある山が山ある。 プレイヤーは一つの山に石が個あるとき、個に減らすことができる。ただしはを割り切れなければならない。
解法
のときは明らかに後手勝ち。 とする。 が偶数ならば後手は先手と全く同じように操作ができるから後手勝ち。 が奇数ならば先手が最初につの山をにすれば、上と同じ戦略が取れるから先手勝ち。
A Chessboard Game
概要
Programming Problems and Competitions :: HackerRank
のチェス盤に石がつ置いてある。 プレイヤーはにある石つをの いずれかに移動させる。ただし盤面外に移動させることはできない。 手を打つことができなったプレイヤーの負けである。
解法
メモ化再帰。
Nim Game
普通のNimなので略。
Misère Nim
概要
Programming Problems and Competitions :: HackerRank
山のNimをする。ただし普通のNimと違うところは 最後に石を取った人が負け (手が打てなくなったプレイヤーが勝ち) という点である。
解法
まずすべての山が1個の石からなるケースを考える。 このときは山の数が偶数なら先手勝ち、奇数なら後手勝ちである。
それ以外のとき、を(普通のNimと同じように)すべての山の石の個数の xorをとったものしてのとき、かつそのときに限り、後手勝ちであることを示す。
今、先手番でとし、先手が手を打つことでこれがになったとする。
このとき、後手番ですべての山の石がとなることは無いことが分かる。 もしそうなったとすると、仮定から先手が選んだ山以外の石の数はすべてであり、 先手が選んだ山はもともと個より多くの石があったことが分かる。 しかしこのような状況はの下では明らかに起こりえない。
これより、後手番では少なくともつの山は個より多い石がある。 石が個より多い山がちょうどつあるときは、その山をかに減らすことで、 山の数が奇数となるようにすべての山をにする ことができるので後手が勝つ。 そのような山がつより多くあると、次の先手番ではすべての山が1個の石からなることはない。 従って通常のNimと同じようにしてとなるように後手は手を打つことができ、 帰納的に後手勝ちであることがわかる。
逆に先手番でとすると、上の後手番の議論をそのまま適用できるので先手勝ちである。
よってすべての山が個の石である場合を例外扱いすることで、普通のNimと同じように解ける。
解説だと全部のときだけ場合分けすればいいとしか書いてないし、 それが正しそうな理由もよく分からなかった。 自分は実験してなんとなく規則性を見つけて適当に投げた。 実験せずに気付けるかと言われると微妙。
Nimble Game
概要
Programming Problems and Competitions :: HackerRank
個の箱が一列に並んでいて、と番号が付いている。 各箱には石が個入っており、プレイヤーは番目の箱にある石つを箱に移すことができる。 先に手を打つことができなくなったプレイヤーの負けである。
解法
位置にある石はそれより小さいのどこへでも動かせる。 これはNimのつの山にある石の個数が個であるときの状況とちょうど対応している。 よって がなら後手勝ちである。
Poker Nim
概要
Programming Problems and Competitions :: HackerRank
山にそれぞれ個石がある。 プレイヤーは各ターンでつの山から個以上の石を取り除くか、あるいは追加することができる。 ただし、石を追加できる回数は各プレイヤー、各山に対して高々回までである(個数は任意)。 最後の石を取り除いたほうが勝ちである。
解法
石を追加しないNimと全く同じ結果になる。 つまり、のとき、かつそのときに限り、後手必勝となる。 のときは先手が石を取り除こうが追加しようが、後手は先手と同じことをすればNim和はになる。 また石の追加は高々回までしかできず、必ず有限回で終わるので後手必勝。
のときは適当に石を取り除いての状態に持っていけるので先手必勝である。
Tower Breakers, Revisited!
概要
Programming Problems and Competitions :: HackerRank
山にそれぞれ個石がある。 プレイヤーはつの山にある個の石をまで減らすことができる。ただしはの 約数でなければならない。 最後の石を取り除いたほうが勝ちである。
解法
山がつで個石があるとする。 このときのgrundy数がどうなるか考える。 のある約数のgrundy数をとすると、の任意の約数にも から遷移できるので、のgrundy数は少なくとも以上である。 これをのすべての約数にわたって考えればとなる。
よくよく考えるとこれはの重複を含めた素因数の個数(例えばなら)と一致することがわかる (素因数でを割ったものならどれでも最大になるため) ので、各のこれを調べて最後にそれらのNim和をとればよい。
Tower Breakers, Again!
概要
Programming Problems and Competitions :: HackerRank
山にそれぞれ個石がある。 プレイヤーはつの山にある個の石を、個の石からなる個の山に分けることができる。 ただしでなければならない。 最後の石を取り除いたほうが勝ちである。
解法
基本的につ前の問題と同じで重複を含めた素因数の個数がgrundy数となる。 ただしを素因数にもつときは一度だけしか数えない(のグランディ数がとなるから)。
Chessboard Game, Again!
概要
Programming Problems and Competitions :: HackerRank
のチェス盤にいくつか石が置いてある。 つのマスに石が複数置いてあっても良い。 プレイヤーはにある石つをの いずれかに移動させる。ただし盤面外に移動させることはできない。 手を打つことができなったプレイヤーの負けである。
解法
素直にgrundy数を計算すれば良い。 盤面がで、ありうる遷移が高々なので愚直に計算しても十分に間に合う。 位置から動かせる手についてが成り立つから、 が小さいものから順に計算することができる。
Digits Square Board
概要
Programming Problems and Competitions :: HackerRank
のマスに整数が書かれている。 プレイヤーは盤面の面積がより大きく、かつ素数でないような数字が少なくともつ書かれているとき、 盤面を水平方向か垂直方向につに分割することができる。 手を打つことができなくなったプレイヤーの負けである。
解法
素直にgrundy数を計算すれば良い。 でメモ化再帰する。 素数でないものが部分長方形に入っているかを累積和で前計算しておけば、盤面が分割できるかどうかはで判定できる。 上の状態があり、各状態からの分割方法はあるので、 全体でで計算できる。
Fun Game
概要
Programming Problems and Competitions :: HackerRank
長さのつの数列がある。 プレイヤーはから、プレイヤーはから交互に数字を選んでいく。 ただしがすでに選ばれていたらを選ぶことができず逆も同様。 なのでちょうど回の操作でゲームは終わる。
各プレイヤーが選んだ数の総和を計算し、大きい方が勝ち、同じなら引き分けである。
解法
この手のつの数列から片方を選ぶみたいな問題は適当な評価値を決めて、 大きい方から選んだりdpしたりすることが多い気がするのでそうする。
このゲームは次のようなゲームに置き換えられる。
- プレイヤーは初期点としてを持っている。
- 数列 がある。
- プレイヤーはから数字を一つ消すことができ、プレイヤーは選んだ数だけプレイヤーの点数を減らせる。
- 最後にプレイヤーの点数が正ならばプレイヤーの勝ち、なら引き分け、負ならプレイヤーの勝ち。
なのでを計算、ソートして、数字が大きいものから順番に消す、点数を減らすことを交互にすればよい。
Powers Game
概要
Programming Problems and Competitions :: HackerRank
文字列がある。 プレイヤーは交互にをかのどちらかにつずつ書き換える。 最後にすべてのが無くなったら数式を計算し、で割りきれたら後手勝ち、そうでなければ先手勝ち。
解法
だけを気にすればいいから、現れる数字は実質だけとみなせる。 また、なるものがあれば、お互いに打ち消すように手を指すことができる (片方がに書き換えたらもう片方はに変える)ので、奇数個あるものだけ着目すれば良い。
あとは のようにをbitとして使いメモ化再帰で解ける。 なのでから順番に前計算しておけば良い。
Deforestation
Programming Problems and Competitions :: HackerRank
既出。同じ問題がhttps://beta.atcoder.jp/contests/agc017/tasks/agc017_dにある。 ハッケンブッシュ(Hackenbush)というゲームがあってそれの特殊な形である。
Tower Breakers - The Final Battle
概要
Programming Problems and Competitions :: HackerRank
個の石がある。となるまでプレイヤーは以下の操作を交互にする。
- プレイヤーはとなるように自由に石を分割する。
- プレイヤーはこの中から番目の山を選び、としてゲームを続ける。このときコイン枚を得る。
プレイヤーはプレイヤーが得られるコインの枚数を最小化、プレイヤーは最大化しようとする。 このとき最終的に得られるコインの枚数はいくらか。
解法
小さいケースで実験するとがある程度大きくなっても答えは大きくならないと予想ができる。
そこでとする。 明らかには単調増加になるから、となるような最大のが求める答えである。 番目の山を選ぶとコインを払うことになるから、 となる。 でとなるから愚直に計算しても実行時間は十分間に合う。