Day 168-Q1 — 2026-10-03 | Turning Corners(コイン反転ゲームの Grundy 数は nim 積。単独コイン (x,y) の値は (x−1)⊗(y−1))

2026-10-03 赤色 Master (Phase 8+) ★★★★★★★★★ ゲーム理論+競技数学(焦点帯 M1、M3 にまたがる)。2 次元のコイン反転ゲームは「コイン 1 枚ずつの Grundy 数の XOR」で解ける。その 1 枚の値が、足し算(XOR)ではなく nim 積(Conway のニム乗算) になるのがこの問題の核

問題

無限に広がる盤面 $\{(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 の表と一致を確認した。

概念図

Turning Corners: (x,y)=(4,3) の表コインと (x',y')=(2,1) を選んだ手表→裏反転反転反転x →(右)。y は上向き。長方形の 4 隅 (4,3),(2,3),(4,1),(2,1) を裏返す単独コインの値 g(x,y) = (x-1) ⊗ (y-1)y\x1234100002012330231403122⊗3=1, 3⊗3=2。通常の積(6, 9)でも XOR でもない

ヒント(クリックで段階的に開示)

ヒント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コイン反転ゲームは「1 枚ずつ」に切り離せる

表の位置の集合を盤面とする。1 手は「$(x,y)$ を表→裏にし、他の 3 隅を反転」。他の 3 隅は、表だった位置が裏に、裏だった位置が表に変わる。これは「その位置のコイン 1 枚の盤面の Grundy 数を XOR で足す」ことと同じ効果を持つので、盤面全体の Grundy 数は表コインそれぞれの単独の値の XOR になる(Sprague–Grundy の定理 + コイン反転ゲームの標準的な議論。証明は書いていないが、検証は下の全状態探索で行った)。

2単独コインの値を表にする

$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$ はコードで出す。

3値が nim 積になる

$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 になる点とも整合する。

4nim 積を 32 ビットで速く

上位・下位 $h$ ビットに割る再帰を、最下段(8 ビット)だけ 256×256 の表に置き換えた。割る段数は 32→16→8 の 2 段で、1 段あたり再帰 3 回(Karatsuba 型)なので 1 回の積が表引き 9 回。座標の上限を $2^{32}$ に抑えたのは、**積が $2^{32}$ 未満の閉じた体に収まる**ので、64 ビット版(再帰 3 段、27 回)を使わずに済むため。

5通常の積や XOR でなぜ駄目か

全 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、例 2 Second、例 3 First
  • 実行時間(実測): $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 の原典確認

自己評価

自分の回答

気づき・メモ