Day 177-Q1 — 2026-10-13 | 3 行の Chomp((b,c) ごとに後手勝ちの a がただ 1 つ、という性質で O(N^3) 状態を O(N^2) 個の値に縮める)

2026-10-13 赤色 Master (Phase 8+) ★★★★★★★★★ ゲーム理論(焦点帯 M1)。Chomp は「先手必勝」だけは戦略盗み論法で分かるが、勝ち方の公式は知られていない。3 行の局面 $(a,b,c)$ を全部調べると $O(N^3)$ 状態・1 状態 $O(N)$ 手で $O(N^4)$。1 行目だけを縮める手を見ると「$(b,c)$ を固定したとき後手勝ちの $a$ は高々 1 つ」が分かり、その値 $P(b,c)$ を mex で順に決めれば $O(N^2)$ 個の値で全局面が判定できる

問題

チョコレートの板が 3 行に並んでいる。1 行目(一番下)の長さが $a$、2 行目が $b$、3 行目が $c$ で $a\ge b\ge c\ge0$、$a\ge1$。1 行目の左端の 1 片は毒である。

2 人が交互に次の手を指す。

  • 行 $r\in\{1,2,3\}$ と、その行の今の長さより短い $x\ge0$ を選び、行 $r$ とそれより上のすべての行の長さを $\min(\text{今の長さ},x)$ にする(選んだ片とその右上をすべて食べる)
  • ただし 1 行目で $x=0$(毒を食べる)は選べない

手が無い(板が毒 1 片 $(1,0,0)$ だけ)プレイヤーの負けである。

$Q$ 個の局面 $(a,b,c)$ について、両者が最善を尽くしたとき先手が勝つなら First、後手が勝つなら Second を出力せよ。

入力形式

Q
a_1 b_1 c_1
...
a_Q b_Q c_Q

制約

#制約
1$1\le Q\le2\times10^5$
2$0\le c_i\le b_i\le2000$
3$\max(b_i,1)\le a_i\le10^{18}$

入出力例

入力例1

6
2 1 0
3 1 1
4 1 1
7 4 3
8 4 4
1000000000000000000 3 1

出力例1

Second
Second
First
Second
Second
First

(1 つ目は 2 行の Chomp でよく知られた後手勝ち $a=b+1$。2 つ目 $(3,1,1)$ は $c>0$ なので 2 行の公式が使えない例で、$P(1,1)=3$。3 つ目は $a$ が 1 つずれるだけで先手勝ちになる。最後の $(b,c)=(3,1)$ には後手勝ちの $a$ が存在しない(1 行目を 2 に縮めた $(2,2,1)$ が後手勝ちなので、どんな $a$ でもそこへ動ける)。6 局面とも、全状態のミニマックス探索と一致)

背景と出典

  • Chomp は Gale(1974)が名付け、それ以前に Schuh(1952)が約数のゲームとして考えた、と私は記憶している(原典は本セッションで未確認)。長方形の板では先手必勝であることが戦略盗み論法で示せるが、勝ち手を作る一般の方法は知られていない
  • 3 行の Chomp は Zeilberger の “Three-Rowed CHOMP”(Advances in Applied Mathematics, 2001 と記憶、未確認)がコンピュータで調べた対象で、「$(b,c)$ を固定すると後手勝ちの $a$ は高々 1 つ」という見方もそこで使われていたと記憶している。本問の問題文・制約・入力例は自作で、性質は本セッションの全探索で確かめた
  • Day161〜176 の不偏ゲームは Grundy 数で和を扱ったが、本問は 1 局面の勝敗だけを問う。Grundy 数を全状態で求める道は $O(N^3)$ 状態が要り、$N=2000$ では 13 億状態で届かない

概念図

局面 (a,b,c) = (7,4,3)。P(4,3) = 7 なので後手勝ち(入力例 4) 1 行目 a = 7 2 行目 b = 4 3 行目 c = 3 毒(食べられない) 緑: 1 行目を x=5 に → (5,4,3)。x≥b の手は b,c を変えない → 後手勝ちの a は (b,c) ごとに高々 1 つ 橙: 2 行目を y=2 に → (7,2,min(3,2)) = (7,2,2)。後手勝ち ⇔ 7 = P(2,2) 青: 3 行目を z=1 に → (7,4,1)。後手勝ち ⇔ 7 = P(4,1)(P(4,1) は無し) P(b,c):後手勝ちになる唯一の a(— は無し) c=0 c=1 c=2 c=3 c=4 c=5 b=0 1 b=1 2 3 b=2 3 2 4 b=3 4 — 5 6 b=4 5 — 6 7 8 b=5 6 — 7 5 9 10 c=1 の列が b≥3 で無し: 1 行目を 2 に縮めた (2,2,1) が後手勝ちだから

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

ヒント1(方向性)

局面 $(a,b,c)$ から「1 行目だけを $x$($b\le x<a$)に縮める」手を指すと $(x,b,c)$ になり、$b,c$ は変わらない。$(a,b,c)$ と $(a',b,c)$($a<a'$)が両方とも後手勝ちになることはありうるか。

ヒント2(アプローチ)

ありえない(大きい方から小さい方へ 1 手で行けるから)。よって $(b,c)$ ごとに後手勝ちの $a$ は高々 1 つで、それを $P(b,c)$(無ければ「無し」)と書く。$(a,b,c)$ からの手を 3 種類に分ける。

  • 1 行目を $x<b$ に: $(x,x,\min(c,x))$。$a$ によらない
  • 2 行目を $y<b$ に: $(a,y,\min(c,y))$。後手勝ち $\iff a=P(y,\min(c,y))$
  • 3 行目を $z<c$ に: $(a,b,z)$。後手勝ち $\iff a=P(b,z)$
ヒント3(誘導)
  • 1 行目を $x<b$ に縮めた $(x,x,\min(c,x))$ のどれかが後手勝ちなら、$P(b,c)$ は無し
  • そうでなければ $P(b,c)$ は「$\max(b,1)$ 以上で、集合 $\{P(y,\min(c,y))\}_{y<b}\cup\{P(b,z)\}_{z<c}$ に入らない最小の $a$」(mex)
  • $b$ の小さい順、同じ $b$ では $c$ の小さい順に決める。集合を Python の整数のビットで持てば、mex は「下位から最初の 0 ビット」で求まる

模範解答 (Python)

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


def main():
    data = sys.stdin.buffer.read().split()
    q = int(data[0])
    qs = [(int(data[1 + 3 * i]), int(data[2 + 3 * i]), int(data[3 + 3 * i])) for i in range(q)]
    n = max(b for _, b, _ in qs)
    NONE = -1
    # P[b][c]: (a,b,c) が後手勝ち(P 局面)になる唯一の a。無ければ NONE
    P = [[NONE] * (b + 1) for b in range(n + 1)]
    # rowmask[c]: y<b についての P(y, min(c,y)) をビットで持つ(2 行目を y に縮める手の行き先)
    rowmask = [0] * (n + 1)
    # dead[c]: 1 行目を x (1<=x<b) に縮めた (x,x,min(c,x)) が P になる x があるか
    dead = [False] * (n + 1)
    for b in range(n + 1):
        colmask = 0                       # z<c についての P(b,z)(3 行目を z に縮める手の行き先)
        Pb = P[b]
        lo = b if b >= 1 else 1
        for c in range(b + 1):
            if dead[c]:
                v = NONE
            else:
                x = (rowmask[c] | colmask) >> lo
                v = lo + (~x & (x + 1)).bit_length() - 1   # lo 以上で、どちらの集合にも無い最小の a
                colmask |= 1 << v
            Pb[c] = v
        for c in range(n + 1):
            v = Pb[c if c < b else b]
            if v >= 0:
                rowmask[c] |= 1 << v
                if b >= 1 and v == b:     # (b,b,min(c,b)) が P → 以後この c では 1 行目を b に縮めて勝てる
                    dead[c] = True
    out = []
    for a, b, c in qs:
        out.append("Second" if P[b][c] == a else "First")
    print("\n".join(out))


main()

計算量: $P$ の表は $O(N^2)$ 個($N=\max b$)。各値の mex は長さ $O(N)$ ビットの整数演算 1 回なので全体 $O(N^3/w)$($w$ は機械語の幅)。$N=2000,Q=2\times10^5$ で 0.77 s・152 MB、$N=3000$ で 1.84 s・226 MB(Python 3.14.8、Apple M5 Pro、負荷平均 4〜13 での実測、起動込み)。

Step-by-Step 解説

11 行目だけを縮める手が「一意性」を生む

$(a',b,c)$ から 1 行目を $a$($b\le a<a'$)に縮めると $(a,b,c)$ になる。もし両方が後手勝ちなら、後手勝ちの局面から後手勝ちの局面へ 1 手で行けることになり矛盾。よって $(b,c)$ ごとに後手勝ちの $a$ は高々 1 つ。全探索($a\le60,b\le24$ の 14624 局面)でも、どの $(b,c)$ でも後手勝ちは 1 つ以下だった。

2手を 3 種類に分け、$a$ への依存を見る

  • 1 行目を $x\ge b$ に: $(x,b,c)$。$x<a$ の全部が「先手勝ち」であることが必要 → $a$ を最小に選べば自動で満たされる($x<a$ はどれも、下の集合に入っていて後手勝ちへ動ける)
  • 1 行目を $1\le x<b$ に: $(x,x,\min(c,x))$。$a$ によらないので、1 つでも後手勝ちなら $(b,c)$ の全局面が先手勝ち($P(b,c)$ は無し)。これを dead[c] で持つ
  • 2 行目・3 行目を縮める手: 行き先が後手勝ちになる $a$ はそれぞれ 1 つだけ($P$ の値)。これらを避ける

3mex で $P(b,c)$ を決める

$$P(b,c)=\operatorname{mex}_{\ge\max(b,1)}\Bigl(\{P(y,\min(c,y))\}_{0\le y<b}\ \cup\ \{P(b,z)\}_{0\le z<c}\Bigr)$$

(dead[c] なら無し)。始まりは $P(0,0)=1$(毒 1 片は手が無いので後手勝ち)。$P(1,0)=2$ は 2 行の公式 $a=b+1$ と一致する。

4集合をビットで持つ

2 行目の手の集合は $c$ ごとに rowmask[c] として、$b$ が 1 増えるたびに $P(b,\min(c,b))$ を足す。3 行目の手の集合は同じ $b$ の中で colmask に足していく。mex は x = (rowmask[c] | colmask) >> lo の最下位の 0 ビットで、(~x & (x+1)).bit_length() - 1。集合(set)で 1 つずつ数える版は $N=2000$ で 15.20 s、ビット版は 0.61 s(どちらも表作りだけ、実測)。

5質問に答える

表ができれば $(a,b,c)$ は「$a=P(b,c)$ なら後手勝ち」。$a$ が $10^{18}$ でも比べるだけ。$N=2000$ での $P$ の最大値は 3416($\approx1.71N$)、表の 2003001 個のうち 827587 個(41%)が「無し」だった。

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

案計算量採否理由
全局面のミニマックス(メモ化)$O(A\cdot N^2\cdot(A+N))$検算用のみ$a$ が $10^{18}$ まであり、$a$ を状態に持てない
全局面の Grundy 数同上不採用和を問わないので勝敗だけで足りる。Grundy 数では一意性が使えない
2 行の公式 $a=b+1$ を流用$O(1)$不採用(誤り)$c>0$ で崩れる。全探索 14624 局面中 490 で誤答(実測)
「1 行目を $x<b$ に縮める手」を見落とす(dead なし)同じ不採用(誤り)454 局面で誤答(実測)。$(b,c)=(3,1)$ など「後手勝ちが無い」組を作ってしまう
mex を 3 行目の集合だけ/2 行目の集合だけで取る同じ不採用(誤り)それぞれ 260・490 局面で誤答(実測)
mex を set で 1 つずつ数える$O(N^3)$不採用(遅い)$N=1000$ で 1.32 s、$N=2000$ で 15.20 s(表作りだけ、実測)
mex をビット演算で(本解)$O(N^3/w)$採用$N=2000$ で表作り 0.61 s

前提が変わったら

  • $b$ が $10^4$ 以上なら $O(N^2)$ 個の表そのもの($5\times10^7$ 個)がメモリに載らない。表を作らず、質問の $(b,c)$ に必要な行だけを作る工夫が要る(本セッションでは試していない)
  • 4 行以上なら「$(b,c,d)$ ごとに $a$ が 1 つ」は同じ論法で成り立つが、表が $O(N^3)$ になる
  • 和(複数の板)を問われたら、勝敗だけでは足りず Grundy 数が要り、一意性による圧縮が使えない。この場合は $a$ も小さく制限するしかない

よくあるミス

ミス原因正しい書き方
2 行の公式 $a=b+1$ を 3 行でも使う小さい例からの一般化$c>0$ で崩れる(入力例 2 の $(3,1,1)$)
「後手勝ちの $a$ は必ずある」と思うmex は必ず値を返すので1 行目を $x<b$ に縮めた先が後手勝ちなら無し(入力例 6)
mex の下限を $b$ にして $b=0$ で $a=0$ を返す毒の片を忘れる下限は $\max(b,1)$
3 行目を縮める手の集合を $c$ をまたいで共有しない内側のループで初期化し忘れ/しすぎ同じ $b$ の中で $c$ を増やしながら足す
rowmask に $P(b,c)$ を足す($\min(c,b)$ でなく)2 行目を $b$ に縮めると 3 行目も $\min(c,b)$ になることを忘れる3 行目は 2 行目より長くなれない

次のステップ

  • 発展1: 4 行の Chomp で同じ表を作り、$b,c,d\le60$ でどこまで計算できるか測る
  • 発展2: 「無し」になる $(b,c)$ の割合($N=2000$ で 41%)が $N$ とともにどう変わるかを調べる
  • 発展3: 2 枚の 3 行 Chomp の和を Grundy 数で解き、一意性が使えなくなる理由を確かめる

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

  • 全探索との照合(実測): $1\le a\le60$、$0\le c\le b\le\min(a,24)$ の 14624 局面をメモ化ミニマックスで解き、本解と全件一致。後手勝ちは 215 局面で、どの $(b,c)$ でも 1 つ以下
  • 誤った方法(実測、同じ 14624 局面): 2 行の公式 490、dead なし 454、3 行目の集合なし 490、2 行目の集合なし 260 で誤答
  • 表の作成時間(実測、表作りだけ): set 版 $N=500/1000/1500/2000$ で 0.17/1.32/5.73/15.20 s、ビット版 0.03/0.12/0.33/0.61 s
  • 全体(実測、起動込み、$Q=2\times10^5$、$a$ は $10^{18}$ まで乱数): $N=2000$ で 0.77 s・152 MB、$N=3000$ で 1.84 s・226 MB
  • $N=2000$ の表: $P$ の最大 3416、「無し」は 2003001 個中 827587 個
  • 扱っていない範囲: Zeilberger の論文の内容確認、4 行以上、和のゲーム

自己評価

自分の回答

気づき・メモ