HDU ~ 4388 ~ Stone Game II (博弈论)

题意: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
#include
#include
#include
#include
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
*/

你可能感兴趣的:(【博弈论】)