题目链接: 见这里
题意: 有n堆石子,分别有a1,a2,”’,an个。两个游戏者轮流操作,每次可以选择一堆,拿走至少石子,但不能拿走超过一半的石子。比如,有3堆石子,每堆分别有5,1,2个,则再下一轮中,游戏者可以从第一堆中拿1个或者2个,第2堆中不能拿,第3堆只能拿一个。谁不能拿石子,谁就输。
解题方法:本题和NIM游戏有些差别,但是也可以看做n个单堆游戏之和。遗憾的是,即是是单堆游戏,由于ai的范围太大,也不能定义递推出所有的sg函数。但是我们可以递推出小范围的sg函数,看看有没有规律:
小范围打表程序如下:

//LA 5059 SG打表
#include <stdio.h>
#include <string.h>
const int maxn = 100;
int SG[maxn];
int vis[maxn];
int main()
{
    SG[1] = 0;
    for(int i = 2; i <= 30; i++){
        memset(vis, 0, sizeof(vis));
        for(int j = 1; j * 2 <= i; j++) vis[SG[i - j]] = 1;
        for(int j = 0; ; j++){
            if(!vis[j]){
                SG[i] = j;
                break;
            }
        }
        printf("%d\n", SG[i]);
    }
    return 0;
}
/* 1 0 2 1 3 0 4 2 5 1 6 3 7 0 8 4 9 2 10 5 11 1 12 6 13 3 14 7 15 当n为偶数时,SG(n) = n/2,但n为奇数时似乎没有什么规律.但是当把n为偶数的值全部删除后得到的数列为 0 1 0 2 1 3 0 4 2 5 1 6 3 7 */

所以就开心写出AC代码了

//LA 5059 main.cpp
#include <bits/stdc++.h>
using namespace std;
long long SG(long long x){
    return x%2 == 0 ? x / 2 : SG(x / 2);
}
int main()
{
    int T; scanf("%d", &T);
    while(T--){
        int n;
        long long a, v = 0;
        cin >> n;
        for(int i = 0; i < n; i++){
            cin >> a;
            v ^= SG(a);
        }
        if(v) puts("YES");
        else puts("NO");
    }
    return 0;
}