問題
無限に広がる盤面 $\{(x,y): x,y\ge1\}$ の $N$ 個の相異なる格子点に、表向きのコインが置かれている(他は裏)。先手・後手が交互に次の操作を 1 回行う。
- 表向きのコイン $(x,y)$ を 1 枚選び、$x'<x$、$y'<y$($x',y'\ge1$)を満たす $(x',y')$ を 1 つ選ぶ。長方形の 4 隅 $(x,y),(x',y),(x,y'),(x',y')$ のコインをすべて裏返す(表→裏、裏→表)。選んだ $(x,y)$ は表→裏になる
操作できなくなった方が負け。両者が最善を尽くすとき、先手が勝つなら First、後手が勝つなら Second を出力せよ。
入力形式
N
x_1 y_1
...
x_N y_N
制約
| # | 条件 |
|---|---|
| 1 | $1\le N\le2\times10^5$ |
| 2 | $1\le x_i,y_i\le2^{32}$ |
| 3 | 点 $(x_i,y_i)$ はすべて相異なる |
| 4 | 入力はすべて整数 |
入出力例
入力例1
1
3 3出力例1
First(コイン 1 枚 $(3,3)$ から $(x',y')=(1,1)$ を選ぶと盤面は $\{(3,1),(1,3),(1,1)\}$ になる。行き先のどれかが後手負けになる、というのが先手勝ちの意味)
入力例2
2
2 3
3 2出力例2
Second入力例3
3
2 2
3 3
3 4出力例3
First背景と出典
「長方形の隅を裏返す」ゲームは Turning Corners と呼ばれる。私の記憶では Winning Ways(Berlekamp–Conway–Guy)の coin-turning games の章にあり、2 次元の積ゲームの Grundy 数が 1 次元の値の nim 積になる定理(Tartan 定理)として紹介されている。nim 積は Conway の *On Numbers and Games* の定義。本セッションでは文献を開いておらず、帰属・定理名・番号は未確認。
この問題で使える事実は 2 つで、どちらも下の検証ログで確かめた(証明は本ファイルに無い)。
1. コイン反転ゲームでは、盤面の Grundy 数は「表のコイン 1 枚だけの盤面の Grundy 数」の XOR(同じ位置に 2 枚は置けないので重複の心配は無い)。理由: 1 手で反転する隅のうち、最大の隅だけが表→裏と決まっていて、残りは「裏返し」=その位置のコインを足し引きする操作になり、Grundy 数の XOR で表せる。 2. 1 枚の値 $g(x,y)=(x-1)\otimes(y-1)$($\otimes$ は nim 積)。$8\times8$ 盤面の全 64 値で mex の表と一致を確認した。
概念図
ヒント(クリックで段階的に開示)
ヒント1(方向性)
コイン 1 枚の盤面だけを考える。$(x,y)$ の表コインから $(x',y')$ を選ぶと、盤面は表コインが $(x',y),(x,y'),(x',y')$ の 3 枚になる。この Grundy 数は 3 枚の値の XOR。したがって $g(x,y)=\operatorname{mex}\{g(x',y)\oplus g(x,y')\oplus g(x',y')\}$。
ヒント2(アプローチ)
$g$ の表を $x,y\le 8$ で作ってみる。$g(1,*)=g(*,1)=0$ で、$g(2,2)=1$、$g(2,3)=2$、$g(3,3)=3$ … 通常の積 $(x-1)(y-1)$ とも XOR とも合わない。実は「加法が XOR、乗法が nim 積」の体(ニム体)の積になっている。
ヒント3(誘導)
nim 積は再帰で定義される。$a,b<2^{2h}$ を上位 $h$ ビットと下位 $h$ ビットに分け $a=a_1F+a_0$、$b=b_1F+b_0$($F=2^h$)とすると、$F\otimes F=F\oplus(F/2)$ なので $$a\otimes b=\bigl((a_1\otimes b_1)\oplus(a_1\otimes b_0)\oplus(a_0\otimes b_1)\bigr)F\ \oplus\ (a_0\otimes b_0)\ \oplus\ \bigl((a_1\otimes b_1)\otimes (F/2)\bigr)$$ Karatsuba 型に $(a_1\oplus a_0)\otimes(b_1\oplus b_0)$ を使えば再帰呼び出しは 3 回。
模範解答 (Python)
模範解答を表示する(まず自力で解いてから)
import sys
def build_table():
# 8 ビット同士の nim 積の表。1 ビット(0/1 の通常の積)から倍々に作る
def mul(a, b, h):
if a < 2 or b < 2:
return a * b
m = h >> 1
mask = (1 << m) - 1
a1, a0, b1, b0 = a >> m, a & mask, b >> m, b & mask
c = mul(a1, b1, m)
d = mul(a0, b0, m)
e = mul(a1 ^ a0, b1 ^ b0, m)
return ((e ^ d) << m) ^ d ^ mul(c, 1 << (m - 1), m)
return [[mul(a, b, 8) for b in range(256)] for a in range(256)]
T = build_table()
def nim_mul(a, b, h=32):
# a, b < 2^h の nim 積。h = 8 で表引き
if h == 8:
return T[a][b]
m = h >> 1
mask = (1 << m) - 1
a1, a0, b1, b0 = a >> m, a & mask, b >> m, b & mask
c = nim_mul(a1, b1, m)
d = nim_mul(a0, b0, m)
e = nim_mul(a1 ^ a0, b1 ^ b0, m)
return ((e ^ d) << m) ^ d ^ nim_mul(c, 1 << (m - 1), m)
def main():
data = sys.stdin.buffer.read().split()
n = int(data[0])
x = 0
for i in range(n):
a = int(data[1 + 2 * i]) - 1
b = int(data[2 + 2 * i]) - 1
x ^= nim_mul(a, b)
print("First" if x else "Second")
main()
計算量: 1 回の nim 積は再帰 2 段(32→16→8)で $3^2=9$ 回の表引き、全体 $O(N)$。表の構築は 65536 エントリ。実測(Python 3.14.7、M1 Mac)で $N=2\times10^5$、座標が $2^{32}$ 以下のランダム入力が 0.8〜1.1 s(計測時の機械の混み具合で揺れる)。
Step-by-Step 解説
表の位置の集合を盤面とする。1 手は「$(x,y)$ を表→裏にし、他の 3 隅を反転」。他の 3 隅は、表だった位置が裏に、裏だった位置が表に変わる。これは「その位置のコイン 1 枚の盤面の Grundy 数を XOR で足す」ことと同じ効果を持つので、盤面全体の Grundy 数は表コインそれぞれの単独の値の XOR になる(Sprague–Grundy の定理 + コイン反転ゲームの標準的な議論。証明は書いていないが、検証は下の全状態探索で行った)。
$g(x,y)=\operatorname{mex}_{x'<x,\,y'<y}\{g(x',y)\oplus g(x,y')\oplus g(x',y')\}$。$x=1$ または $y=1$ の行・列は手が無いので 0。$g(2,2)$ は $(x',y')=(1,1)$ だけで行き先の値は $0\oplus0\oplus0=0$、mex は 1。$g(2,3)$ は $(1,1)$ から 0、$(1,2)$ から $g(1,3)\oplus g(2,2)\oplus g(1,2)=1$ が出るので mex は 2。手計算はここまでにして、$x,y\le8$ はコードで出す。
$8\times8$ の 64 値すべてで $g(x,y)=(x-1)\otimes(y-1)$ と一致した(実測)。nim 積は XOR を加法、$\otimes$ を乗法とした体になる(結合・分配の法則を、32 ビットの乱数 2000 組で破りに行って違反 0 件)。体なので「$a\otimes b=0$ なら $a=0$ か $b=0$」が成り立ち、$x=1$ や $y=1$ の行・列で 0 になる点とも整合する。
上位・下位 $h$ ビットに割る再帰を、最下段(8 ビット)だけ 256×256 の表に置き換えた。割る段数は 32→16→8 の 2 段で、1 段あたり再帰 3 回(Karatsuba 型)なので 1 回の積が表引き 9 回。座標の上限を $2^{32}$ に抑えたのは、**積が $2^{32}$ 未満の閉じた体に収まる**ので、64 ビット版(再帰 3 段、27 回)を使わずに済むため。
全 65536 状態の判定(実測)で、通常の積 $(x-1)(y-1)$ を各コインの値にすると 12288 状態、$x\otimes y$(1 を引かない)は 18432 状態、$(x-1)\oplus(y-1)$ は 24576 状態で誤り。「$-1$」は座標が 1 始まりで、$x=1$ の列に手が無い(値 0)ことの反映。
迷った他案と採らなかった理由
| 案 | 計算量 | 採否 | 理由 |
|---|---|---|---|
| 盤面の全状態を再帰で探索 | 指数 | 検算用のみ | $4\times4$ なら 65536 状態で全部解ける。座標 $2^{32}$ は不可 |
| 単独コインの $g(x,y)$ を mex の表で作る | $O(x^2y^2)$ | 規則の発見用のみ | $8\times8$ までは一瞬だが、座標が大きいと不可。値の規則(nim 積)を見つける用途 |
| 64 ビット版の nim 積(再帰 3 段) | 27 回の表引き | 不採用 | 座標を $2^{32}$ に絞れば 32 ビット版で足りる。上限の方を問題側で決めた |
| 表を使わず 1 ビットまで再帰 | $3^5=243$ 回 | 不採用 | 表(256×256)の構築は 65536 回の再帰呼び出しで 1 回きり。コイン 2×10^5 枚なら表が得 |
| 本解(8 ビット表+Karatsuba 型再帰) | $O(N)$ | 採用 | 全 65536 状態と一致 |
前提が変わったら:
- **座標が $2^{64}$ まで**なら再帰を 1 段足す(積は $2^{64}$ 未満に閉じる)。Python では 27 回の表引きで約 3 倍遅くなる見込み(未測定)
- 3 次元(直方体の 8 隅)の反転ゲームなら、値は 3 つの nim 積になるはずだが、私の記憶では Tartan 定理は 2 つの 1 次元ゲームの積について述べたもので、3 次元への一般化は本セッションでは未確認・未検証
- 反転する隅の条件が違う(たとえば Ruler ゲームや Turning Turtles)なら $g$ が変わる。表を作って規則を探し直す
よくあるミス
| ミス | 原因 | 正しい書き方 |
|---|---|---|
| $x\oplus y$ や $xy$ で $g$ を作る | 「積」「和」という言葉に引きずられる | nim 積(12288〜24576/65536 状態で誤答) |
| 座標から 1 を引かない | 盤面が 1 始まりで、手の無い行・列が値 0 になることを見落とす | nim_mul(x-1, y-1)(18432/65536 で誤答) |
| 分配則を使うつもりで通常の乗算を混ぜる | $a\otimes(b\oplus c)$ は $a\otimes b\oplus a\otimes c$ だが、$a\cdot(b\oplus c)$ は違う | 積はすべて nim_mul、加法は ^ |
| $F\otimes F$ を $F\cdot F$ と書く | 通常の積と同じ見た目の記号 | $F\otimes F=F\oplus(F/2)$(本解は mul(c, 1 << (m-1), m) の項) |
次のステップ
- 発展1: 勝ち手の個数を出力する(盤面の XOR を $X$ とし、各コイン $(x,y)$ で $t=g(x,y)\oplus X<g(x,y)$ となる $(x',y')$ の組を数える。nim 積の逆元・除算が要る)
- 発展2: nim 積の逆元 $a^{-1}$ を、$a^{2^{32}-2}$ のべき乗(nim 積の繰り返し二乗)で求める
- 発展3: Tartan 定理の証明を、Winning Ways か Conway の本で確認する(本セッションでは未確認)
検証ログ(本セッションで実行した数値)
- nim 積の公理(実測): 32 ビットの乱数 3 つ組 2000 件で、結合則 $a\otimes(b\otimes c)=(a\otimes b)\otimes c$ と分配則 $a\otimes(b\oplus c)=a\otimes b\oplus a\otimes c$ の違反 0 件。既知値 $2\otimes2=3,\ 4\otimes4=6,\ 8\otimes8=13$ が一致(この 3 値は私の記憶による既知値で、出典未確認。一致は確認した)
- 単独コインの値(実測): mex の定義から作った $g(x,y)$ が $x,y\le8$ の全 64 値で $(x-1)\otimes(y-1)$ と一致
- 全状態探索との照合(実測): $4\times4$ 盤面の全 65536 状態を全手探索で解き、$(x-1)\otimes(y-1)$ の XOR による判定と全件一致(不一致 0)。後手必勝は 16384 状態。プログラム全体(標準入力経由)は空でない 300 状態の無作為抽出で不一致 0
- 誤った方法(実測): $x\otimes y$ は 18432/65536、$(x-1)\oplus(y-1)$ は 24576/65536、$(x-1)(y-1)$ は 12288/65536 状態で誤答
- 入力例(実測): 例 1
First、例 2Second、例 3First - 実行時間(実測): $N=2\times10^5$、座標 $\le2^{32}$ で 0.8〜1.1 s
- 扱っていない範囲: Tartan 定理・コイン反転ゲームの Grundy 数の XOR 分解の証明、座標が $2^{32}$ を超える場合、3 次元版、勝ち手の出力、盤面が $4\times4$ より大きい全状態探索($5\times5$ は $2^{25}$ 状態で未実施)、Winning Ways・Conway の原典確認