先介绍一下Nim博弈

如果这堆石头数量异或和为0,先手必败,否则先手必胜

这边给出证明:

一个人最终会输,也就是说他需要面对没有石头的那种情况,这边给两个概念:

一个人面对石头数量异或和为0的时候,这个人处于必败态

一个人面对石头数量异或和不为0的时候,这个人处于必胜态

这个人处于必败态的时候,下一步无论取走多少石头都能让异或和变得不等于0,这个时候对手就处于必胜态

这个人处于必胜态的时候,我们要取走一些石头让异或和为0,我们去找有异或和 S 二进制最高位的那一堆石头(因为最高位是1,石头堆里面肯定有一个有异或和最高位的那一堆石头),记为arr[i],除了arr[i]之外的石头数量异或和为S ^ arr[i],我们在这一堆石头中拿走arr[i] - (arr[i] ^ S)个石头,此时异或和变为S ^ arr[i] ^ (arr[i] - (arr[i] - (arr[i] ^ S))) = S ^ arr[i] ^ (arr[i] ^ S) = 0,这个时候就能让对手处于必败态

差不多就是这个样子

最终的必败态也就是0了,证明结束

//

对于这题来说,小A如果一开始面对的异或和不为0的话,那他游戏开始前不取就行了,这样他肯定能赢

如果他面对的异或和是0的话,这里他肯定要取走k个石头让总异或和不为0,那只需要考虑一下能不能取走k个(也就是最大值需要大于等于k)和取走之后异或和会不会变(也就是k等不等于0)

这边贴代码

#include <bits/stdc++.h>
using namespace std;
void solve() {
    // nim博弈
    int n,k;
    cin >> n >> k;
    vector<int> arr(n);
    for (auto& v : arr)cin >> v;
    int xorsum = 0;
    for (auto& v : arr){
        xorsum ^= v;
    }
    if(xorsum == 0){
        int maxv = *max_element(arr.begin(),arr.end());
        if (maxv < k || k == 0) {
            cout << "NO\n";
            return;
        }
        cout << "YES\n";
    }
    else{
        cout << "YES\n";
    }
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
    solve();
    return 0;
}