4bitにっき

ぽよ

Game Theory (HackerRank) : Game of Stones

問題

Programming Problems and Competitions :: HackerRank
N個の石を持つ山が1つだけある。
2人のプレイヤーは各ターンで2,3,または5個だけ石を取り除くことが出来、先に石を取れなくなった方の負け。
勝つのはどちらか。

テストケース数T \leq 100
N \leq 100

解法

Grundy数で殴った。
想定解法は dp[i]=石がi個は勝ちか負けか というDP。

蟻本を読んで初めてGrundy数を学んだ。
(多分)以下の様な性質を満たしていればGrundy数をNimの山のように扱えるので、XORで勝敗が分かる。

Grundy数xについて
・Grundy数が0~x-1である状態に1手で行けて、xには行けない。
・少なくとも、「それ以上操作出来ない負けの状態」ならx=0。

この性質を満たしていればGrundy数が増えてももう一方のプレイヤーが1手で元に戻せるので問題にならない。
Grundy数は、定義より再帰的に求められる。(DPできる)

実装

#include <bits/stdc++.h>
using namespace std;

#define int long long

int memo[101];

int Grundy(int n)
{
	if (memo[n] != -1) return memo[n];
	bool s[4] = {};
	int a[] = { 2, 3, 5 };
	for (int i = 0; i < 3; i++)
	{
		if (n < a[i]) continue;
		s[Grundy(n - a[i])] = true;
	}
	int res = 0;
	while (s[res]) res++;
	return memo[n] = res;
}

signed main()
{
	fill(memo, memo + 101, -1);
	int T;
	cin >> T;
	for (int i = 0; i < T; i++)
	{
		memo[0] = 0;
		int N;
		cin >> N;
		cout << (Grundy(N) ? "First" : "Second") << endl;
	}
	return 0;
}