石子

GitHub跳转原题关系图返回列表

判定唯一必胜态:只剩一堆且为偶数时 Alice 一次拿光,其余情况 Bob 总能拖延致胜。

OJ: roj

题目 ID: 10010

难度:普及-

标签:博弈论python

创建: 2026-10-02 17:38

更新: 2026-10-04 22:06

题目描述

Alice 与 Bob 玩石子。多组数据(读到 EOF),每组给定 nn 堆石子,第 ii 堆 aia_i 颗。Alice 先手,每次必须拿偶数颗(至少 2 颗);Bob 每次必须拿奇数颗(至少 1 颗)。无法操作者输。∑n<106\sum n < 10^6,1⩽ai<1091 \leqslant a_i < 10^9。

思路

Alice 只能拿偶数颗,因此她一次拿光的唯一可能是某堆本身为偶数且这是最后一堆;其余情况下 Bob 总能在任意非空堆拿 1 颗续命,把必败局面留给 Alice。故仅当 n=1n = 1 且 a1a_1 为偶数时输出 YES,否则输出 NO。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-09-29 11:30
# update_at: 2026-09-29 11:40

import sys
from collections.abc import Iterator


def next_case(tokens: Iterator[int]) -> tuple[int, list[int]] | None:
    """读出下一组数据 (n, a);输入耗尽时返回 None。"""
    try:
        n = next(tokens)
    except StopIteration:
        return None
    return n, [next(tokens) for _ in range(n)]


def alice_wins(a: list[int]) -> bool:
    """判定该局面是否 Alice 必胜。"""
    # 唯一的必胜态:只剩一堆且为偶数 —— Alice 一次拿光,Bob 面对空局
    return len(a) == 1 and a[0] % 2 == 0


def solve() -> None:
    tokens = iter(map(int, sys.stdin.buffer.read().split()))
    out: list[str] = []

    while (case := next_case(tokens)) is not None:
        _n, a = case
        out.append("YES" if alice_wins(a) else "NO")

    print("\n".join(out))


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-04 22:05
 * update_at: 2026-10-04 22:06
 */
#include <cstdio>
#include <iostream>
using namespace std;

typedef long long ll;

ll n, x;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    // 多组数据读到 EOF
    while (cin >> n) {
        // 唯一需要关心的是:是否只剩一堆且该堆为偶数
        if (n != 1) {
            // n >= 2 时 Alice 必败:Bob 总能在任意非空堆拿 1 颗续命
            for (ll i = 1; i <= n; ++i) cin >> x;
            cout << "NO\n";
        } else {
            cin >> x;
            cout << (x % 2 == 0 ? "YES" : "NO") << "\n";
        }
    }
    return 0;
}