直接给结论,不考虑作弊的情况下,所有石子数的异或和不为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");
}

京公网安备 11010502036488号