题意:T组测试数据,给你一个N,每堆有a[i]个石子,两个人轮流操作谁不能操作谁输,问先手赢还是输。
操作分两步: 第一步为:选择任意一堆石子假定石子个数为a,拿走个数不为0的一些石子使得该堆石子剩余k个并且保证(0 < k < a,k^a < a),^为异或符号。第二步为:加入一堆新的石子,石子个数为k^a,当然你也可以使用技能使得加入的石子个数变为(2k)^a。不过每个人每局游戏只能使用一次技能。
思路:先考虑一堆且不用技能的情况。每次操作相当于把一堆数目为a的石子分为了两堆k,k^a。因为牵扯到异或,我们可以从二进制观察,发现操作其实就是把a数字中的1拆出去一部分。比如:a=1101,可以拆为1000,101两堆。所以我们发现,如果a数字二进制中'1'的个数为X,那么我们对于出自于a这一堆的石子,共可以进行X-1次操作。如果X-1为奇数先手赢,否则先手输。
考虑N堆的情况,总共可操作次数为奇数先手赢,否则先手输。
现在考虑用技能,其实用技能就相当于乘2,二进制多了一个0但是对'1'的个数没有影响,所以技能没什么用。
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int MAXN = 1e3 + 5;
int main()
{
int T, CASE = 1; scanf("%d", &T);
while (T--)
{
int n; scanf("%d", &n);
int ans = 0;
while (n--)
{
int t; scanf("%d", &t);
ans += __builtin_popcount(t) - 1; //二进制下1的个数。G++函数
}
if (ans&1) printf("Case %d: Yes\n", CASE++);
else printf("Case %d: No\n", CASE++);
}
return 0;
}
/*
3
2
1 2
3
1 2 3
4
1 2 3 3
*/