Day 170-Q1 — 2026-10-05 | Misère Dawson's Kayles(隣り合う 2 本だけを倒す。長さ 1 の列は「死んだ列」なので捨ててよいが、Grundy 数の XOR も Nim の misère 規則も使えない)

2026-10-05 赤色 Master (Phase 8+) ★★★★★★★★★ ゲーム理論(焦点帯 M1)。Day169-Q1(Kayles の misère 版)の続き。今回は手が「隣り合う 2 本」だけなので、長さ 1 の列はどの手にも関わらず状態から捨てられる。この「死んだ成分を捨てる」正規化は misère でも正しいが、「等しい 2 列を消す」正規化は誤り、という線引きを数字で確かめる

問題

ピンが一列に隙間なく並んだ「列」が $N$ 本あり、$i$ 本目の列には $a_i$ 本のピンがある。2 人が交互に、次の手を 1 回ずつ行う。

  • どれか 1 列から、隣り合う 2 本のピンを倒す(1 本だけ倒すことはできない)

倒したピンは取り除かれ、列の途中を倒すと列は 2 つに分かれる(例: 長さ 6 の列の 2・3 本目を倒すと、長さ 1 と長さ 3 の 2 列になる)。

最後に手を指した人の負け(misère ルール)。言い換えると、手番が回ってきたときに指せる手が 1 つも無ければ、その人の勝ち。両者が最善を尽くすとき、先手が勝つなら First、後手が勝つなら Second を出力せよ。$T$ 個のテストケースに答えること。

入力形式

T
N_1
a_1 a_2 ... a_{N_1}
N_2
...

制約

#条件
1$1\le T\le2\times10^5$
2$1\le N$、$1\le a_i$
3各テストケースで $\sum a_i\le50$
4入力はすべて整数

入出力例

入力例1

6
1
1
1
2
1
3
1
12
2
4 4
3
1 3 6

出力例1

First
Second
Second
Second
Second
First

($\{1\}$ は先手に手が無いので先手の勝ち。$\{2\}$ と $\{3\}$ は先手が唯一の手を指すと後手に手が無くなり、先手が最後に指したので負け。$\{1\}$・$\{12\}$・$\{4,4\}$ は下の「よくあるミス」の 3 つの近道がそれぞれ誤る最小の例)

背景と出典

この「隣り合う 2 本を倒す」ゲームは八進表記で 0.07、Dawson's Kayles と呼ばれる。T. R. Dawson のチェス詰め問題(Dawson's chess、八進 0.137)と同じ構造で、列の長さが 1 ずれるだけの関係にある、と私は理解している(Dawson の原典と Guy–Smith(1956)の八進ゲーム論文は本セッションでは未確認)。

通常ルール(最後に指した人が勝ち)では Sprague–Grundy の定理で各列の Grundy 数 $G(n)$ の XOR が答えを決める。本セッションで $G(n)$ を $n<194$ まで計算すると、$G(n)\ne G(n+34)$ となる $n$ は $\{0,15,17,32,35,52\}$ で、$n\ge53$ では周期 34(実測)。文献で知られる「周期 34」と合う(文献の例外位置との照合は未実施)。

misère では和のゲームの勝敗が Grundy 数だけでは決まらない(Day169-Q1 と同じ)。Conway の「tame でないゲーム」の整理、Plambeck の misère 商(misère quotient)が和の制約なしで解く道具だが、本問は和 50 以下という制約で全状態を数え上げられることを使う(misère 商の原典は未確認)。

概念図

左: 長さ 1 の列は手が無いので捨ててよい(ゲーム木が同型) 長さ 1: 手なし → 捨てる 長さ 3 長さ 6 赤 2 本を倒すと 6 → 2 と 2 に分かれる {1,3,6} の状態は (3,6)。先手勝ち(First) 右: {4,4} は「等しい 2 列を消す」と空=先手勝ちに見える {4,4} 負け 端の 2 本中の 2 本 {2,4} 勝ち {4} 勝ち 4 の中 2 本4 の端 2 本 {2} 負け {} 勝ち 「勝ち/負け」は、その局面で手番の人から見た結果 線引き: ゲーム木が同型になる変換(長さ 0・1 を捨てる、並べ替え)だけが misère でも正しい。G⊕G=0 による消去は通常ルール専用

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

ヒント1(方向性)

局面は「各列の長さの多重集合」で決まる。さらに、長さ 1 の列ではどんな手も指せず、他の列の手にも影響しない。だから長さ 1 の列は最初から捨ててよい(misère でも正しい。指せる手の集合が変わらないので、ゲーム木がまったく同じになる)。長さ 0 も同様。

ヒント2(アプローチ)

長さ 2 以上の列だけを昇順タプルにして状態にし、メモ化全探索する。和 50 以下で長さ 2 以上の部分だけからなる分割は 204225 個(実測)。1 状態からの手は「どの長さの列か(同じ長さは 1 回)×左に残す本数(対称なので半分)」。空の状態(指せる手が無い)は手番側の勝ち。

ヒント3(誘導)
def win(state):            # 長さ 2 以上の列の昇順タプル
    if not state: return True                 # 手が無い = 手番側の勝ち(misère)
    for 各列 h(同じ長さは 1 回):
        for left in range(0, (h - 2)//2 + 1):
            right = h - 2 - left
            nxt = 残りの列 + [left, right のうち 2 以上のもの] を昇順に
            if not win(nxt): return True
    return False

メモはテストケース間で共有する。

模範解答 (Python)

模範解答を表示する(まず自力で解いてから)
import sys
sys.setrecursionlimit(10000)


def main():
    data = sys.stdin.buffer.read().split()
    t = int(data[0])
    pos = 1
    memo = {}

    def win(state):
        # state: 長さ 2 以上の列を昇順に並べたタプル。手番の人が勝つか(misère)
        if not state:
            return True          # 動ける手が無い = 相手が最後の手を打った → 手番側の勝ち
        r = memo.get(state)
        if r is not None:
            return r
        res = False
        lst = list(state)
        seen = set()
        for idx, h in enumerate(lst):
            if h in seen:
                continue
            seen.add(h)
            rest = lst[:idx] + lst[idx + 1:]
            for left in range(0, (h - 2) // 2 + 1):
                right = h - 2 - left
                nxt = rest + [v for v in (left, right) if v >= 2]
                if not win(tuple(sorted(nxt))):
                    res = True
                    break
            if res:
                break
        memo[state] = res
        return res

    out = []
    for _ in range(t):
        n = int(data[pos]); pos += 1
        a = sorted(v for v in map(int, data[pos:pos + n]) if v >= 2); pos += n
        out.append("First" if win(tuple(a)) else "Second")
    print("\n".join(out))


main()

計算量: 状態数は「和 $\le50$、部分がすべて 2 以上の分割」の 204225 個が上限。1 状態あたりの手は $O(S^2/2)$ だが、勝ち手が見つかれば打ち切る。204225 個の全状態を 1 入力で与えて 1.45 s・1.46 s(Python 3.14.7、M1 Mac、2 回実測)。

Step-by-Step 解説

1長さ 1 の列を捨ててよい理由

長さ 1 の列に対して指せる手は無く、他の列の手の結果にも現れない。だから局面 $X\cup\{1\}$ と $X$ はゲーム木がまったく同じ(同型)で、通常ルールでも misère でも勝敗が一致する。本問では手を倒した後の残り(left, right)が 1 になったときも捨てる。Day169-Q1 の Kayles(1 本倒しもある)では長さ 1 にも手があるので捨てられなかった。状態数は和 40 以下で Kayles 側 215307 個に対し本問は 37337 個(実測)、だから和の上限を 50 に上げられた。

2等しい 2 列は消せない

通常ルールでは $G\oplus G=0$ なので同じ長さの 2 列を消せる。misère ではゲーム木が変わる($\{4,4\}$ は消すと空=先手勝ちに見えるが、正解は Second)。「捨ててよい」のはゲーム木が同型になる変換だけ、が線引き。

3Grundy 数の XOR が誤る理由

$\{1\}$ の Grundy 数は 0 で、通常ルールなら「後手勝ち」。misère では先手に手が無い=先手の勝ち。終了条件が反転するので、和 40 以下の全 215307 局面(長さ 1 の列も含む全分割)のうち 53046 局面で誤る(実測)。Kayles の 1121 局面よりずっと多いのは、長さ 1 の列(と $G=0$ の列)がたくさんある局面で、どれも「指せない」ことが勝ちに効くため。

4Nim の misère 規則の移植も誤る

「全部の列の $G\le1$ なら XOR=0 で先手勝ち、そうでなければ通常どおり」を移すと 25380 局面で誤る。最小の反例は $\{12\}$($G(12)=2$ で XOR≠0 → 規則は First、正解は Second)。

5正規化の検証

正規化をしない「ピンの 0/1 文字列」をそのまま全探索した結果と、両端がピンで長さ 16 以下の全 32768 文字列で一致(実測)。

迷った他案と採らなかった理由

案計算量採否理由
通常ルールの Grundy XOR$O(S^2)$不採用53046/215307 局面で誤り
Nim の misère 規則を Grundy 経由で移す同上不採用25380/215307 誤り、最小反例 $\{12\}$
等しい 2 列も消して状態を減らす状態数が減る不採用26570/215307 誤り、最小反例 $\{4,4\}$
長さ 1 を捨てた多重集合の全探索(本解)状態 204225採用ピン文字列の全探索と 32768 件一致
misère 商(Plambeck)表引き不採用本セッションで商を構成・検証していない。和の上限が無いならこれが本命

前提が変わったら:

  • 和の上限が 55 になると、ランダムに選んだ $10^5$ 局面で 2.64 s、60 で 4.39 s(実測)。60 を超えるなら misère 商か、Grundy 数が 0・1 の列を別扱いする部分的な理論が要る
  • 通常ルールなら Grundy XOR で $O(S^2)$、周期 34 を使えば列の長さが $10^{18}$ でも $O(1)$
  • 1 本倒しも許す(Kayles)なら長さ 1 を捨てられず、状態数が増える(Day169-Q1)

よくあるミス

ミス原因正しい書き方
Grundy XOR で判定misère でも SG 定理が効くと思う状態の全探索(53046/215307 誤答、最小反例 $\{1\}$)
「$G\le1$ のときだけ反転」Nim の規則がどのゲームにも効くと思う同上(25380/215307 誤答、最小反例 $\{12\}$)
同じ長さの 2 列を消す$G\oplus G=0$ の持ち込み消さない(26570/215307 誤答、最小反例 $\{4,4\}$)
長さ 1 の列を残したまま状態にする正解だが遅い捨てる(ゲーム木が同型なので正しい)
空の局面を「手番側の負け」にする通常ルールの終了条件のまま空で手番 = 手番側の勝ち

次のステップ

  • 発展1: Dawson's chess(0.137、1 本倒すと両隣も倒れる)の misère 版を本問に帰着させ、列の長さがどうずれるかを確かめる
  • 発展2: 本問の全状態の表から「$X$ と $Y$ を足すと勝敗が変わる局面」を数え、misère 商の考え方(どの列を区別しなければならないか)を体験する
  • 発展3: Plambeck の misère 商の原典で 0.07 の商を探し、本問の全探索と照合する(未確認)

検証ログ(本セッションで実行した数値)

  • 正規化の照合(実測): 両端がピンで長さ 1〜16 の全 32768 個の 0/1 文字列を、正規化しない全探索と本解で比べて不一致 0
  • 誤った方法(実測): 和 40 以下の全分割 215307 局面で、Grundy XOR 53046・Nim 規則の移植 25380・等しい 2 列の消去 26570 局面誤答。和 20 以下(2713 局面)ではそれぞれ 1239・116・237。最小反例は $\{1\}$・$\{12\}$・$\{4,4\}$
  • Grundy 数(実測): $G(0..19)=0,0,1,1,2,0,3,1,1,0,3,3,2,2,4,0,5,2,2,3$。$n<160$ で $G(n)\ne G(n+34)$ は $n\in\{0,15,17,32,35,52\}$
  • 状態数(実測): 和 40 以下で長さ 2 以上だけの分割は 37337 個、和 50 以下で 204225 個
  • 実行時間(実測): 和 50 以下の全 204225 状態を 1 入力で 1.45 s・1.46 s。和 50/55/60 の状態からランダムに $10^5$ 局面で 1.19/2.64/4.39 s(これが和 $\le50$ にした理由)
  • 入力例(実測): First Second Second Second Second First
  • 扱っていない範囲: misère 商の構成、和 51 以上、周期 34 の文献の例外位置との照合、Dawson・Guy–Smith・Plambeck の原典

自己評価

自分の回答

気づき・メモ