直接给结论,不考虑作弊的情况下,所有石子数的异或和不为0则先手胜利,否则后手胜利。此结论的推导和证明请自行搜索了解。

若不作弊且先手的小A胜利即此时异或和xorSum不为0,则直接输出"YES",否则考虑小A能否作弊(因为不作弊肯定输,所以看作弊能否改变输的局面)。对于这些堆石子,若想从中的某堆石子拿走k个石子,前提是存在一堆石子的数量大于等于k,否则小A无法作弊。再考虑可以作弊的情况,他(她)可以选择某堆大于等于k的石子拿走k个石子,这样的操作的贡献实际上就是对异或和xorSum再异或k(具体证明请自行分析),最后判断此时的异或和xorSum是否不为0,不为0则小A胜利输出"YES",否则表示即使作弊也不能改变局面输出"NO"。

而实际上只要k不为0且可以作弊的情况下,小A一定可以反败为胜。证明:有我们上述的结论,小A在不作弊的情况下是必输的局面,即此时的异或和为0,假设此时有作弊的条件(存在一堆石子的数量大于等于k),对异或和再次异或k,由于0异或除0以外的任何数都不为0,那么有结论可知小A可以获胜输出"YES"。

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>

int main() {
  int n,k;
  std::cin >> n >> k;

  std::vector<int> a(n);
  for(int i = 0; i < n; i++){
    std::cin >> a[i];
  }

  //计算异或和
  int xorSum = std::accumulate(a.begin(),a.end(),0,std::bit_xor<int>());

  if(xorSum){//异或和不为0,小A直接胜利
    std::cout << "YES\n";
    return 0;
  }

  //找所有堆中石子数量的最大值
  int max = *std::max_element(a.begin(),a.end());

  if(max < k){//没有作弊的条件
    std::cout << "NO\n";
    return 0;
  }

  //看k是否不为0,k不为0则可以反败为胜,否则仍旧会输
  std::cout << (k?"YES\n":"NO\n");
}