本题是经典 Nim 游戏 的变种。

核心思路

核心观察

本题基于经典 Nim 游戏,其胜负由所有石子堆数量的 异或和(XOR sum) 决定:

  • 若异或和 ,先手必胜;
  • 若异或和 ,先手必败。

小A在游戏开始前可执行一次特殊操作:从某一堆中恰好拿走 个石子 注意不是(需满足该堆 ),之后正常开始游戏(小A仍为先手)。

关键数学性质如下:

当原始异或和为 0 时,若存在某堆 ,则操作后的新异或和为

由于 ,必有 ,因此该值
即:只要能合法执行一次 操作( 且有堆足够大),小A就能将必败态转为必胜态

此外:

  • ,相当于无法改变局面;
  • 若所有堆均 ,也无法操作。

算法步骤

  1. 读入整数 (堆数)和 (可提前拿走的石子数)。
  2. 读入 个石子堆数量 ,同时计算:
    • 总异或和 total = a[0] ^ a[1] ^ ... ^ a[n-1]
    • 最大堆大小 mx = max(a[i])
  3. 判断胜负:
    • total != 0:小A无需操作即可获胜 → 输出 "YES"
    • 否则(total == 0):
      • k == 0mx < k:无法有效操作 → 输出 "NO"
      • 否则:存在合法操作使新局面异或和 → 输出 "YES"

正确性分析

  • 情况一:原始异或和
    小A作为先手,在标准 Nim 游戏中已有必胜策略,无需使用预操作。故输出 "YES" 正确。

  • 情况二:原始异或和

    • :小A不能改变任何堆,局面不变,仍为必败态 → "NO" 正确。
    • :无一堆满足 ,无法操作 → "NO" 正确。

    • 设选中堆为 ,操作后该堆变为
      新异或和为 (因 ),
      小A作为新局先手,面对非零异或和,必胜 → "YES" 正确。
条件 结果 说明
无法改变局面,仍必败
操作非法 无合法操作,必败
必胜

综上,算法覆盖所有情况,逻辑严密。

复杂度分析

  • 时间复杂度
    仅需一次遍历计算异或和与最大值。
  • 空间复杂度
    存储石子堆数组;若边读边处理,可优化至 额外空间。

数学逻辑推导

==命题 A==(平衡态不可维持) 若 ,则任何合法操作都会使新异或和

==命题 B==(非平衡态可修复) 若 ,则存在至少一个合法操作,使新异或和

证明命题 A: 任何操作导致

设当前

玩家必须选择某堆 ,将其从 改为 ,其中 (因至少取 1 个)。

新异或和为:

由于 ,必有 ,因此:

==命题 A 得证==:从 出发,任何操作都会破坏平衡。

证明命题 B: 存在操作使

设当前

最高位 1 的位置(例如 ,则 )。

因为 的第 位为 1,说明有奇数个堆在第 位为 1。
因此,至少存在一个堆 满足其第 位为 1

对这个堆 ,定义:

我们验证:

  1. (操作合法)
    • 因为 的最高位是 ,且 的第 位为 1,
      所以 会将 的第 位变为 0,而更高位不变,
  2. 新异或和为 0

命题 B 得证:从 出发,总能一步归零。

归纳论证: 是必败态

  • 基础:终止状态 满足 ,且当前玩家输。
  • 归纳
    • 若当前 ,由命题 A,玩家只能转移到
    • 对手面对 ,由命题 B,总能回到
    • 如此循环,最终当前玩家将面对 而输

因此,所有 的状态都是必败态
的状态都是必胜态。

在标准 Nim 游戏中:

  • 若初始异或和 先手必败,后手必胜
  • 若初始异或和 先手必胜

代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n,k;cin>>n>>k;
    vector<int>v(n);
    int total=0,mx=0;
    for(int i=0;i<n;i++){
        cin>>v[i];
        total^=v[i];//总异或值
        mx=max(mx,v[i]);//堆里最大石子数量
    }
    if(total!=0){cout<<"YES";return 0;}
    if(mx<k)cout<<"NO";
    else if(k!=0)cout<<"YES";
    else cout<<"NO";

}