//理清其中的原理是最重要的,我还有点晕,不过我可以先记忆下来
//1.NIM游戏
//给定N堆物品,第i堆物品有Ai个。
//两名玩家轮流行动,每次可以任选一堆,取走任意多个物品,可把一堆取光,但不能不取。
//取走最后一件物品者获胜。两人都采取最优策略,问先手是否必胜。
//a1^a2……an-1^an!=0,先手必胜
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n,res=0;
cin>>n;
while(n--)
{
int x;
cin>>x;
res^=x;
}
if(res)puts("yes");//先手必胜
else puts("no");
return 0;
}
//2.集合-NIM游戏
//输入m种取法,规定每次取的个数
//输入n堆石子,规定每堆石头的个数
// 1.Mex运算:
// 设S表示一个非负整数集合.定义mex(S)为求出不属于集合S的最小非负整数运算,即:
// mes(S)=min{x};
// 例如:S={0,1,2,4},那么mes(S)=3;
// 2.SG函数
// 在有向图游戏中,对于每个节点x,设从x出发共有k条有向边,分别到达节点y1,y2,····yk,定义SG(x)的后记节点y1,y2,····
// yk的SG函数值构成的集合在执行mex运算的结果,即:
// SG(x)=mex({SG(y1),SG(y2)····SG(yk)})
// 特别地,整个有向图游戏G的SG函数值被定义为有向图游戏起点s的SG函数值,即 SG(G)=SG(s).
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_set>
using namespace std;
const int N=110,M=10010;
int n,m;//n存石头的堆数,m存石头的取法
int s[N];//每次取多少石头
int f[N];//sg的值
int sg(int x)
{
if(f[x]!=-1)return f[x];//已经被更新过
unordered_set<int> S;//存下一个状态
for(int i=0;i<m;i++)
{
int sum=s[i];//便利石头取法
if(x>=sum)S.insert(sg(x-sum));//递归求下一个状态
}
for(int i=0;;i++)
if(!S.count(i))//判断变的sg集合是否存在i(即求mes)
return f[x]=i;
}
int main()
{
cin>>m;
for(int i=0;i<m;i++)cin>>s[i];
cin>>n;
memset(f,-1,sizeof f);//将sg初始化为-1
int res=0;
for(int i=0;i<n;i++)
{
int x;
cin>>x;//输入石头数
res^=sg(x);//类似NIM游戏
}
if(res)puts("yes");
else puts("no");
return 0;
}