問題
位置 $1,2,\dots,10^{18}$ にコインが 1 枚ずつ並び、位置 $x_1<x_2<\dots<x_N$ だけが表、他は裏である。2 人が交互に次の手を指し、指せなくなった(表のコインが無い)人の負け。
- 表のコインを 1 枚選び(位置 $x$)、裏にする。さらに、$x$ より左のコインを 0 枚・1 枚・2 枚選んで裏返してよい(表でも裏でもよい)
裏返すコインの集合が違えば別の手とする。先手が勝つか後手が勝つかを答え、先手が勝つなら勝ち手の数も答えよ。
入力形式
N
x_1 x_2 ... x_N
出力形式: 後手が勝つなら Second。先手が勝つなら 1 行目に First、2 行目に勝ち手の数($2^{64}$ を超えることがある。そのまま出力)
制約
| # | 制約 |
|---|---|
| 1 | $1\le N\le2\times10^5$ |
| 2 | $1\le x_1<x_2<\dots<x_N\le10^{18}$ |
入出力例
入力例1
4
1 2 3 4出力例1
Second(1 枚の Grundy 数は位置 1, 2, 3, 4 で 1, 2, 4, 7。$1\oplus2\oplus4\oplus7=0$)
入力例2
3
2 5 9出力例2
First
4(Grundy 数は 2, 8, 16、XOR は 26。位置 9 を裏にして、残り 10 を「位置 9 より左の 2 枚の Grundy 数の XOR」で作る組が 4 通り: $\{1,11\},\{2,8\},\{4,14\},\{7,13\}$ に当たる位置の組)
入力例3
3
1 999999999999999999 1000000000000000000出力例3
First
847078495393153021(勝ち手の数は 2 枚の組の数え上げで $10^{17}$ 級になる。入力例 1・2 は 13 枚の盤の全状態探索と一致)
背景と出典
- Mock Turtles は Berlekamp–Conway–Guy『Winning Ways』のコイン反転ゲームの 1 つで、Grundy 数が odious 数になる、と私は記憶している(原典は本セッションで未確認)。本問では位置 0〜199 の 1 枚の Grundy 数を mex で計算し、odious 数の列 1, 2, 4, 7, 8, 11, 13, 14, … と 200 個すべて一致することを確かめた
- コイン反転ゲームの和: 表のコインが複数ある局面の Grundy 数は、各表のコイン 1 枚だけの局面の Grundy 数の XOR になる(同じコインを 2 回裏返すと元に戻ることから、裏返しを「表のコインの追加・削除」とみなせる。Lenstra の nim 積の仕事や ONAG の第 14 章にあると記憶、未確認)。本問では 13 枚の盤の全 8191 状態で、この XOR による勝敗判定と勝ち手の数が全探索と一致することを確かめた
- 本問は自作。1 枚・2 枚の場合(Turning Turtles)は Grundy 数が位置そのもので Nim と同じになる。3 枚まで許すと値が odious 数に「ずれる」ところが面白い
概念図
ヒント(クリックで段階的に開示)
ヒント1(方向性)
位置 $x$ の表のコイン 1 枚だけの局面の Grundy 数 $G(x)$ を小さい $x$ で計算してみる。$G$ は 1, 2, 4, 7, 8, 11, 13, 14, … で、2 進で 1 が奇数個の数(odious 数)が小さい順に並ぶ。全体の Grundy 数は表のコインの $G$ の XOR。
ヒント2(アプローチ)
全体の XOR を $X$ とする。表のコイン $r$ を裏にする手で勝つには、残りで $t=X\oplus G(r)$ を打ち消せばよい。
- $t=0$: $r$ だけ裏返す(1 通り)
- もう 1 枚 $a<r$: $G(a)=t$ が必要。$t$ が odious で $t<G(r)$ なら 1 通り
- もう 2 枚 $a<b<r$: $G(a)\oplus G(b)=t$。odious 数どうしの XOR は 1 が偶数個なので、$t$ の 1 の個数が偶数のときだけ
ヒント3(誘導)
2 枚の場合の数は「odious な $u$ で、$u<L$ かつ $u\oplus t<L$($L=G(r)$)」の個数の半分。$u$ が $L$ から初めて離れるビット $k$($L_k=1,u_k=0$)で場合分けし、$t$ の最上位ビット $h$ と比べる:
- $k>h$: $u\oplus t$ も bit $k$ で $L$ より小さい。下位 $k$ ビットは自由で、1 の個数の偶奇は半々 → $2^{k-1}$
- $k<h$: bit $h$ で $u\oplus t$ は $L_h\oplus1$。$L_h=1$ なら小さい → $2^{k-1}$、$L_h=0$ なら 0
- $k=h$: $u\oplus t$ は bit $h$ まで $L$ と同じ。下位で「$w<L$ の下位ビット、かつ偶奇の条件」を数える
模範解答 (Python)
模範解答を表示する(まず自力で解いてから)
import sys
def odd_below(M):
"""[0, M) のうち立っているビット数が奇数(odious)の整数の個数"""
if M <= 0:
return 0
if M % 2 == 0:
return M >> 1
return (M >> 1) + (bin(M - 1).count('1') & 1)
def pairs_count(L, t):
"""odious な u のうち u < L かつ (u ^ t) < L を満たす個数(t は 0 でなく偶数ビット)"""
h = t.bit_length() - 1
res = (L >> (h + 1) << (h + 1)) >> 1 # u が L から離れるビット k が h より上
if L >> h & 1:
low = L & ((1 << h) - 1)
res += low >> 1 # h より下の k >= 1: 下位の自由なビットで偶奇が半々
if low & 1 and bin(L >> 1).count('1') & 1:
res += 1 # k = 0: 偶奇は固定
# k = h: u_h = 0、v_h = 1 = L_h。下位 h ビットで v < L かつ u が奇数ビット
need = (1 - bin(L >> (h + 1)).count('1') - bin(t & ((1 << h) - 1)).count('1')) & 1
o = odd_below(low)
res += o if need else low - o
return res
def grundy(x):
"""位置 x(1 始まり)の表のコイン 1 枚の Grundy 数 = (x-1) 番目の odious 数"""
p = x - 1
return 2 * p + (1 - (bin(p).count('1') & 1))
def main():
data = sys.stdin.buffer.read().split()
n = int(data[0])
xs = [int(v) for v in data[1:n + 1]]
gs = [grundy(x) for x in xs]
X = 0
for g in gs:
X ^= g
if X == 0:
print("Second")
return
total = 0
for g in gs:
t = X ^ g # 残りのコインで作るべき XOR
if t == 0:
total += 1 # 右端の 1 枚だけ裏返す
elif bin(t).count('1') & 1:
total += 1 if t < g else 0 # もう 1 枚: Grundy 数 t の位置 (t>>1)+1 < x
else:
total += pairs_count(g, t) >> 1 # もう 2 枚: 順序なしの組
print("First")
print(total)
main()
計算量: 表のコイン 1 枚につき 60 ビット程度の整数演算が定数回で $O(N\log x)$。$N=2\times10^5$(偶数)で 0.18〜0.23 s、$N=199999$(奇数、2 枚の組を数える場合が主)で 0.29〜0.53 s(Python 3.14.7、M1 MacBook Pro 8GB、負荷平均 11〜18 での実測、起動込み)。
Step-by-Step 解説
11 枚の Grundy 数
位置 $p$(0 始まり)の表のコイン 1 枚から指せる手は「$p$ だけ裏返す」(行き先の Grundy 数 0)、「$a<p$ も裏返す」($G(a)$)、「$a<b<p$ も裏返す」($G(a)\oplus G(b)$)。mex を取ると $G=1,2,4,7,8,11,\dots$。$p$ 番目の odious 数は $2p+[\text{popcount}(p)\text{ が偶数}]$($2p$ と $2p+1$ のうち 1 の個数が奇数の方)。
2なぜ和は XOR か
裏返しを「その位置の表のコインを足す/消す」とみなすと、裏のコインを裏返すのは「表のコイン 1 枚の局面」を新しく足すこと、表のコインを裏返すのはそれを消すこと。同じ局面 2 つは XOR で打ち消し合うので、局面全体は表のコイン 1 枚ずつの局面の和として扱える(13 枚の全状態で確かめた)。
3勝ち手の 3 つの型と偶奇
$t=X\oplus G(r)$ を残り 0〜2 枚で作る。odious 数は 1 の個数が奇数なので、1 枚なら $t$ は奇数個、2 枚なら偶数個(0 以外)。型は $t$ で 1 つに決まる。さらに $X$ の 1 の個数の偶奇は $N$ の偶奇と同じなので、$N$ が偶数なら勝ち手は必ず「もう 1 枚」型、奇数なら「$r$ だけ」か「もう 2 枚」型になる。
4位置の条件を値の条件に
$G$ は単調増加で odious 数を漏れなく並べるので、「位置 $a<r$」⇔「$G(a)$ は $G(r)$ 未満の odious 数」。1 枚型は $t<G(r)$ だけ見ればよく、2 枚型は $L=G(r)$ 未満の odious 数の組を数える。$u$ が odious なら $u\oplus t$ も odious($t$ の 1 が偶数個)なので、条件は「$u$ が odious、$u<L$、$u\oplus t<L$」。順序付きで数えて 2 で割る($t\ne0$ なので $u\ne u\oplus t$)。
5ビットごとの数え上げ
$u<L$ の $u$ は、上から見て初めて $L$ と離れるビット $k$($L_k=1,u_k=0$)で分類できる。ヒント 3 の 3 つの場合のうち、$k\ne h$ は「下位 $k$ ビットが自由で偶奇が半々」なので、$L$ の該当ビットを集めて 1 つ右シフトするだけで和が出る。$k=0$ だけは自由なビットが無いので、上位の 1 の個数で 1 か 0。$k=h$ は $w=u\oplus t$ の下位が $L$ の下位未満で、$\text{popcount}(u)=\text{popcount}(w)+\text{popcount}(t_\text{下位})$ の偶奇条件を満たす $w$ の個数で、これは odd_below で $O(1)$。
迷った他案と採らなかった理由
| 案 | 計算量 | 採否 | 理由 |
|---|---|---|---|
| 全状態探索($2^n$ 状態) | $O(2^n n^3)$ | 検算用のみ | 13 枚の盤まで |
| Turning Turtles と同じく $G(x)=x$ の Nim | $O(N)$ | 不採用(誤り) | 13 枚の全 8191 状態中 640 状態で勝敗を誤る(実測) |
| $G(x)=2(x-1)$(odious の補正を忘れる) | $O(N)$ | 不採用(誤り) | 256 状態で勝敗を誤る(実測) |
| 2 枚の組を順序付きのまま数える | $O(N\log x)$ | 不採用(誤り) | 勝ち手の数が 4004 状態で誤り(実測) |
| 一緒に裏返すコインを表のコインだけに限る | $O(N^2)$ | 不採用(誤り) | 裏のコインも裏返せる。6911 状態で誤り(実測) |
| 桁 DP((u の上限, v の上限, 偶奇) の 8 状態 × 60 ビット) | $O(N\cdot 60\cdot 8)$ | 不採用(遅い) | 正しいが、$N=2\times10^5$ で約 $10^8$ 回の遷移。閉じた式の検算にだけ使える |
| ビットごとの閉じた式(本解) | $O(N\log x)$ | 採用 | 0.29〜0.53 s |
前提が変わったら
- 4 枚まで裏返せるなら Grundy 数は別の列になる(本セッションでは計算していない)。まず mex の表を作り、規則を当ててから全探索で確かめる、という同じ手順になる
- 勝ち手の数を $\bmod$ で求めるなら、Python では同じコードの最後に剰余を取るだけ。C++ なら 2 枚型の個数が $2^{63}$ を超えうるので
__int128が要る - 盤が 2 次元(Turning Corners、Day168)なら 1 枚の値は nim 積になり、本問の odious 数の構造は使えない
よくあるミス
| ミス | 原因 | 正しい書き方 |
|---|---|---|
| $G(x)=x$ とする | Turning Turtles(2 枚まで)と混同 | 3 枚まで許すと odious 数。640/8191 状態で勝敗を誤る(実測) |
| 位置を 1 始まりのまま odious の式に入れる | 添字のずれ | $p=x-1$ として $2p+[\text{popcount}(p)\text{ 偶}]$ |
| 2 枚の組を 2 で割らない | $u$ と $u\oplus t$ を別に数える | 順序付きの個数の半分。4004/8191 状態で誤り(実測) |
| 一緒に裏返す相手を表のコインに限る | 「表のコインを動かす」Nim の感覚 | 位置 $r$ より左なら裏のコインも選べる |
| $k=0$ の場合も $2^{k-1}$ とする | 半々の議論は自由なビットが 1 つ以上のときだけ | $k=0$ は上位ビットの偶奇で 1 か 0 |
次のステップ
- 発展1: 4 枚まで裏返せるゲームの Grundy 数を mex で 200 個計算し、規則を探す
- 発展2: Mock Turtles の misère 版(最後に指した人の負け)を 13 枚の全探索で調べる
- 発展3: 『Winning Ways』のコイン反転ゲームの章で、odious 数になる理由の証明を確かめる(本セッションでは未確認)
検証ログ(本セッションで実行した数値)
- 1 枚の Grundy 数(実測): 位置 0〜199 を mex で計算し、odious 数の先頭 200 個と一致
- 全状態探索との照合(実測): 13 枚の盤の全 8191 状態で、勝敗と勝ち手の数が全件一致(後手勝ち 255 状態、勝ち手の最大 22)。別に 11 枚の盤から 700 状態を抜き出して標準入出力経由でも一致
- 2 枚型の数え上げ(実測): $L<300$、$t<600$(1 が偶数個)の 89700 組で、
pairs_countと総当たりが一致 - 誤った方法(実測、13 枚の全 8191 状態): $G=x$ で勝敗 640、$G=2(x-1)$ で 256、組を順序付きで 4004、相手を表のコインに限ると 6911 状態で誤り
- 実行時間(実測、起動込み): $N=2\times10^5$(偶数、1 枚型だけ、勝ち手 86289 など)0.18〜0.23 s、$N=199999$ で 0.29〜0.53 s(勝ち手は $2.9\times10^{22}$ 程度)。連続する 20 万個の位置では
Second - 扱っていない範囲: 4 枚以上、misère 版、原典の確認