SlideShare a Scribd company logo
1 of 30
Download to read offline
NimとGrundy数の
大雑把な説明
かっさ(@__KasSA)
Nimとは
・一般的に、2人で盤上の石とかコインを取り合う
・1つの山を選択し、そこから1つ以上、好きなだけ取り除ける
・1つも取れなくなったほうが負けになるゲーム
Nimとは
・一般的に、2人で盤上の石とかコインを取り合う
・1つの山を選択し、そこから1つ以上、好きなだけ取り除ける
・1つも取れなくなったほうが負けになるゲーム
必勝法が存在し、ゲームが始まる前に必勝か必敗かわかってしまう
Nimとは
・一般的に、2人で盤上の石とかコインを取り合う
・1つの山を選択し、そこから1つ以上、好きなだけ取り除ける
・1つも取れなくなったほうが負けになるゲーム
必勝法が存在し、ゲームが始まる前に必勝か必敗かわかってしまう
必勝判定は、各山の枚数を XOR でまとめたときの値が
0ではない :先手の勝ち
0である :先手の負け となっている
(ゲーム値) = (0) xor 9 = 9
0ではないので勝ち
9 枚
・9 枚全部取れば勝てる
・強い
1山のとき
2山ある時
4枚 4枚
戦略:先手が取った数だけ
後手が一方の山から取れば常に後手が勝てる
(勝ちの目を維持できる)
(ゲーム値) = 4 xor 4 = 0
0 なので負け
3枚 4枚 2枚 4枚 1枚 4枚 0枚 4枚
3枚 3枚 2枚 2枚 1枚 1枚 0枚 0枚
先手
後手
2山ある時
3枚 5枚
戦略:先手が右の山から2枚取ると、
後手と先手が入れ替わった先の状況が再現できる
(先手の番のゲーム値) = 3 xor 5 = 6
6 なので勝ち
3枚 3枚
(後手の番のゲーム値) = 3 xor 3 = 0
0 なので負け→先手の勝ち
3山ある時
3枚 7枚
のこり枚数の xor が0になるように
相手に手番を渡すことができれば勝ち
今 3 xor 7 xor 5 =1 なので、
3の山を2にすれば、
2 xor 7 xor 5 = 0 を相手に渡せる
Xorについて考えるとうまくいくことが
示せるが割愛
(記事にはNimKの場合で書いたので
K=1としても示せる)
(ゲーム値) = 3 xor 7 xor 5 =1
1 なので勝ち
5枚
N山ある時
3枚 7枚
のこり枚数の xor が0になるように
相手に手番を渡すことができれば勝ち
(ゲーム値) = pile[0] xor pile[1] xor pile[2] xor … xor pile[N-2] xor pile[N-1]
5枚
…
2枚 1枚 7枚
Nimまとめ
・各山のXORを取ると、必勝判定ができる
・各山の枚数を XOR でまとめたときの値が
0ではない :先手の勝ち
0である :先手の負け となっている
ゲームの値。ざっくり言うと0のとき負け、
そうでないとき勝ち
求め方:
集合の非負整数を求める例1:
ある状態から、次の状態のgrundy数 {0,1,2,4,5,6,7,8}が得られたとき
→ ある状態のgrundy数は、3
集合の非負整数を求める例2:
ある状態から、次の状態のgrundy数 {1,2,3,4,5}が得られたとき
→ ある状態のgrundy数は、0
Grundy数
現在の状態から移行できる状態のGrundy数の集合の
うち、存在しない最小の非負整数(mex)
Grundy数
例:Nいっちゃだめゲーム (yukicoder No.008より改変)
Alice,Bobの2人で数字を増加させるゲームをプレイする。0からはじめ
て各プレイヤーは1から3までの数字を選択し、現在の数字に加算する。
最初にN以上の数字を作成した人の負けである。
2人が最適な洗濯をするとして、Aliceが先手のときAliceは必勝か?
Nが与えられるのでSampleみたいに出力してください。(説明をサボらないで)
制約:1≦N≦10^5
Sample Input1: 3
Sample Output1: Alice Win.
Sample Input2: 13
Sample Output2: Bob Win.
Grundy数
例:Nいっちゃだめゲーム (yukicoder No.008より改変)
Alice,Bobの2人で数字を増加させるゲームをプレイする。0からはじめ
て各プレイヤーは1から3までの数字を選択し、現在の数字に加算する。
最初にN以上の数字を作成した人の負けである。
2人が最適な洗濯をするとして、Aliceが先手のときAliceは必勝か?
Nが与えられるのでSampleみたいに出力してください。(説明をサボらないで)
制約:1≦N≦10^5
解いてみてください
次ペーシ解法です
Grundy数
例:Nいっちゃだめゲーム (yukicoder No.008より改変)
Alice,Bobの2人で数字を増加させるゲームをプレイする。0からはじめ
て各プレイヤーは1から3までの数字を選択し、現在の数字に加算する。
最初にN以上の数字を作成した人の負けである。
2人が最適な洗濯をするとして、Aliceが先手のときAliceは必勝か?
Nが与えられるのでSampleみたいに出力してください。(説明をサボらないで)
制約:1≦N≦10^5
O(1)解法 : 周期から (N-1)%(3+1) が0のとき負け、そうでないときは勝ち
O(N)解法 :何も分からないのでにとりあえずGrundy数を求める
Grundy数
O(N)解法 :何も考えずにGrundy数を求める
負けの状態のGrundy数は0。今回負けなのは数字がN-1のとき。
(N-1が回ってくるとNを言わざるをえないから)
Grundy数の配列
N-2 N-1N-4 N-3N-6 N-5N-8 N-7
? 0? ?? ?? ?
20 1 …
?? ? …
Grundy数
O(N)解法 :何も考えずにGrundy数を求める
負けの状態のGrundy数は0。今回負けなのは数字がN-1のとき。
(N-1が回ってくるとNを超えざるをえないから)
Grundy数の配列
N-2 N-1N-4 N-3N-6 N-5N-8 N-7
? 0? ?? ?? ?
20 1 …
?? ? …
N-1の状態から次の状態に移動するとき、どの状態にも移動できない {}
→N-1のgrundy数は0
Grundy数
O(N)解法 :何も考えずにGrundy数を求める
負けの状態のGrundy数は0。今回負けなのは数字がN-1のとき。
(N-1が回ってくるとNを言わざるをえないから)
Grundy数の配列
N-2 N-1N-4 N-3N-6 N-5N-8 N-7
1 0? ?? ?? ?
20 1 …
?? ? …
N-2の状態から次の状態に移動するとき、N-1に移動できる {0}
→N-2のgrundy数は1
Grundy数
O(N)解法 :何も考えずにGrundy数を求める
負けの状態のGrundy数は0。今回負けなのは数字がN-1のとき。
(N-1が回ってくるとNを言わざるをえないから)
Grundy数の配列
N-2 N-1N-4 N-3N-6 N-5N-8 N-7
1 0? 2? ?? ?
20 1 …
?? ? …
N-2の状態から次の状態に移動するとき、N-1にしか移動できない {0}
→N-2のgrundy数は1
N-3の状態から次の状態に移動するとき、N-2,N-1に移動できる {1,0}
→N-3のgrundy数は2
Grundy数
O(N)解法 :何も考えずにGrundy数を求める
負けの状態のGrundy数は0。今回負けなのは数字がN-1のとき。
(N-1が回ってくるとNを言わざるをえないから)
Grundy数の配列
N-2 N-1N-4 N-3N-6 N-5N-8 N-7
1 03 2? ?? ?
20 1 …
?? ? …
N-4の状態から次の状態に移動するとき、N-3,N-2,N-1に移動できる {2,1,0}
→N-4のgrundy数は3
Grundy数
O(N)解法 :何も考えずにGrundy数を求める
負けの状態のGrundy数は0。今回負けなのは数字がN-1のとき。
(N-1が回ってくるとNを言わざるをえないから)
Grundy数の配列
N-2 N-1N-4 N-3N-6 N-5N-8 N-7
1 03 2? 0? ?
20 1 …
?? ? …
N-5の状態から次の状態に移動するとき、N-4,N-3,N-2に移動できる {3,2,1}
→N-5のgrundy数は0
N-1,N-5は負け状態であることがわかった
繰り返すことで、0 に対するGrundy数がわかる。→先手必勝かの判定ができる。
Grundy数
O(N)解法 :何も考えずにGrundy数を求める
負けの状態のGrundy数は0。今回負けなのは数字がN-1のとき。
(N-1が回ってくるとNを言わざるをえないから)
Grundy数の配列
N-2 N-1N-4 N-3N-6 N-5N-8 N-7
1 03 21 03 2
20 1 …
(N-1)%(3+1) …
Grundy数を求めていくと今回の問題では周期がGrundy数に存在して、
周期4だ…ということがわかる
→ 先のO(1)解法がわかる
(N-2)%(3+1)
(N-3)%(3+1)
Grundy数
再帰関数で実装
std::setはlogといっても結構遅いので
Grundy数の最大値が小さいなら、
bitset<MAX> Set や
bool Set[MAX]に
変更すると結構速くなる
問題:とにかく盤面の分割ができるゲームでの必勝判定をしたい
例:分割されるゲーム
Grundy数
その前にNimのGrundy数を考える
Grundy数
NimのGrundy数を考える
Nimの1山のGrundy数は、山にある石やコインの枚数に等しい。
全部の取る選択から、1枚だけ取るまでを選択できるので
Grundy数の定義から枚数に等しい値が得られる。
4枚 3枚 2枚 1枚 0枚
4 3 2 1 0
枚数
Grundy数
Grundy数
NimのGrundy数を考える
Nimの1山のGrundy数は、山にある石やコインの枚数に等しい。
複数山あるときは、
XOR を取れば(なんかよくわからなくても)勝敗判定ができた
今 3 xor 7 xor 5 =1 なので、
3の山を2にすれば、
2 xor 7 xor 5 = 0 を相手に
渡せる
(ゲーム値) = 3 xor 7 xor 5 =1
1 なので勝ち
Grundy数
NimのGrundy数を考える
Nimの1山のGrundy数は、山にある石やコインの枚数に等しい。
複数山あるときは、
XOR を取れば(なんかよくわからなくても)勝敗判定ができた
したがって、Grundy数が求められるゲームが並列してたくさんあるときは、
各ゲームをNimの山として扱い、必勝判定ができる。
Grundy数
NimのGrundy数を考える
Nimの1山のGrundy数は、山にある石やコインの枚数に等しい。
複数山あるときは、
XOR を取れば(なんかよくわからなくても)勝敗判定ができた
したがって、Grundy数が求められるゲームが並列してたくさんあるときは、
各ゲームをNimの山として扱い、必勝判定ができる。
なにかしらのゲームがあったとして、ある時この盤面を分割したとする。
→
(複数に分割)
分割された盤面のGrundy数がわかると、
これはNimに変換できる!
Grundy数
NimのGrundy数を考える
Nimの1山のGrundy数は、山にある石やコインの枚数に等しい。
複数山あるときは、
XOR を取れば(なんかよくわからなくても)勝敗判定ができた
したがって、Grundy数が求められるゲームが並列してたくさんあるときは、
各ゲームをNimの山として扱い、必勝判定ができる。
なにかしらのゲームがあったとして、ある時この盤面を分割したとする。
→
(複数に分割)
分割された盤面のGrundy数がわかると、
これはNimに変換できる!
↓
(Nimにみえる)
それぞれのGrundy数: 4 2 7
(分割前のGrundy数) =4 xor 2 xor 7 = 1
Grundy数まとめ
→
(複数に分割)
・分割された盤面のGrundy数がわかると、
これはNimに変換できる。
↓
(Nimにみえる)
4 2 7
(分割前のGrundy数) =4 xor 2 xor 7 = 1
・Nimの1山のGrundy数は、山にある石やコインの枚数に等しい。
・ゲームの値。0のとき負け、そうでないとき勝ち。
・求め方は、
現在の状態から移行できる状態のGrundy数の集合のうち、
存在しない最小の非負整数。(mex)
忘れないうちに、
HackerRankの 5 days of game theory
を解きましょう!
おわり

More Related Content

What's hot

やさしい整数論
やさしい整数論やさしい整数論
やさしい整数論Kazuma Mikami
 
指数時間アルゴリズム入門
指数時間アルゴリズム入門指数時間アルゴリズム入門
指数時間アルゴリズム入門Yoichi Iwata
 
最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解く最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解くshindannin
 
2SAT(充足可能性問題)の解き方
2SAT(充足可能性問題)の解き方2SAT(充足可能性問題)の解き方
2SAT(充足可能性問題)の解き方Tsuneo Yoshioka
 
ウェーブレット木の世界
ウェーブレット木の世界ウェーブレット木の世界
ウェーブレット木の世界Preferred Networks
 
Rolling Hashを殺す話
Rolling Hashを殺す話Rolling Hashを殺す話
Rolling Hashを殺す話Nagisa Eto
 
2部グラフの最小点被覆の求め方
2部グラフの最小点被覆の求め方2部グラフの最小点被覆の求め方
2部グラフの最小点被覆の求め方Kensuke Otsuki
 
AtCoder Regular Contest 016 解説
AtCoder Regular Contest 016 解説AtCoder Regular Contest 016 解説
AtCoder Regular Contest 016 解説AtCoder Inc.
 
高速フーリエ変換
高速フーリエ変換高速フーリエ変換
高速フーリエ変換AtCoder Inc.
 
AtCoder Regular Contest 030 解説
AtCoder Regular Contest 030 解説AtCoder Regular Contest 030 解説
AtCoder Regular Contest 030 解説AtCoder Inc.
 
AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説AtCoder Inc.
 
Re永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライドRe永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライドMasaki Hara
 
AtCoder Regular Contest 044 解説
AtCoder Regular Contest 044 解説AtCoder Regular Contest 044 解説
AtCoder Regular Contest 044 解説AtCoder Inc.
 

What's hot (20)

Binary indexed tree
Binary indexed treeBinary indexed tree
Binary indexed tree
 
目指せグラフマスター
目指せグラフマスター目指せグラフマスター
目指せグラフマスター
 
WUPC2012
WUPC2012WUPC2012
WUPC2012
 
やさしい整数論
やさしい整数論やさしい整数論
やさしい整数論
 
指数時間アルゴリズム入門
指数時間アルゴリズム入門指数時間アルゴリズム入門
指数時間アルゴリズム入門
 
最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解く最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解く
 
2SAT(充足可能性問題)の解き方
2SAT(充足可能性問題)の解き方2SAT(充足可能性問題)の解き方
2SAT(充足可能性問題)の解き方
 
ウェーブレット木の世界
ウェーブレット木の世界ウェーブレット木の世界
ウェーブレット木の世界
 
Rolling Hashを殺す話
Rolling Hashを殺す話Rolling Hashを殺す話
Rolling Hashを殺す話
 
双対性
双対性双対性
双対性
 
2部グラフの最小点被覆の求め方
2部グラフの最小点被覆の求め方2部グラフの最小点被覆の求め方
2部グラフの最小点被覆の求め方
 
AtCoder Regular Contest 016 解説
AtCoder Regular Contest 016 解説AtCoder Regular Contest 016 解説
AtCoder Regular Contest 016 解説
 
Rolling hash
Rolling hashRolling hash
Rolling hash
 
高速フーリエ変換
高速フーリエ変換高速フーリエ変換
高速フーリエ変換
 
Convex Hull Trick
Convex Hull TrickConvex Hull Trick
Convex Hull Trick
 
AtCoder Regular Contest 030 解説
AtCoder Regular Contest 030 解説AtCoder Regular Contest 030 解説
AtCoder Regular Contest 030 解説
 
AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説AtCoder Regular Contest 039 解説
AtCoder Regular Contest 039 解説
 
Re永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライドRe永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライド
 
Abc009
Abc009Abc009
Abc009
 
AtCoder Regular Contest 044 解説
AtCoder Regular Contest 044 解説AtCoder Regular Contest 044 解説
AtCoder Regular Contest 044 解説
 

Nimとgrundy数の大雑把な説明