Daizhenyang's Coin HDU - 3537
原题链接
考察:博弈论
思路:
这题不会只能说明对sg函数理解不够透彻了(比如我.
明确sg函数是解决所有ICG游戏的通解,而本题很明显是ICG游戏(所有执行步骤与执行者无关).
那么所有面朝上的硬币都可以视为一个起点.以下标为0的面朝上硬币为例,那么sg(0) = 1.由此也可以推到sg(1) = 2.我们可以由翻0~2枚左边硬币的步骤算出sg函数.打表sg函数值,可以发现3 5 6 8 10 12 15...的sg值都是2*i+1.这些数字有什么特点呢?根据猜测(看他人题解),都是二进制1的个数为偶数的数.
坑点:去重,排序
Code:
#include <iostream>
#include <cstring>
#include <set>
using namespace std;
const int N = 110;
int n,f[N];
set<int> s;
//int sg(int x)
//{
// if(f[x]!=-1) return f[x];
// set<int> s;
// s.insert(0);//将x处的硬币翻转
// for(int i=0;i<x;i++)//翻两个
// s.insert(sg(i));
// for(int i=0;i<x;i++)
// for(int j=i+1;j<x;j++)
// s.insert(sg(i)^sg(j));
// for(int i=0;;i++)
// if(!s.count(i)) return f[x] = i;
//}
int lowbit(int x)
{
return x&-x;
}
int get(int x)
{
int cnt = 0;
for(int i=x;i;i-=lowbit(i)) cnt++;
return cnt;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
int x,res = 0;
s.clear();
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
s.insert(x);
}
for(auto it:s)
{
int x = it;
if(!x) res^=1;
else if(get(x)&1) res^=2*x;
else res^=2*x+1;
}
if(res) puts("No");
else puts("Yes");
}
return 0;
}