题目
n堆苹果,每堆ai个
每次可以选一堆然后取若干个连续的苹果
最后一个取苹果的人输(Anti-SG)
问先手是否有必胜策略
思路来源
https://blog.csdn.net/Code92007/article/details/87892307
题解
把所有后继状态打好,
注意到也可从中间截取向两个子游戏转移的后继状态
处理好1-100的sg值的表
然后按Anti-SG判断即可
心得
题不难,但先总结着吧
万一以后忘了呢……
博弈还是得刷刷题找找感觉……
毕竟自己当时sg表都不会打……
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int sg[105],n;
bool vis[105];
bool ok;
int ans;
void getsg()
{
sg[0]=0;sg[1]=1;
for(int i=2;i<=100;++i)
{
memset(vis,0,sizeof(vis));
for(int j=0;j<i;++j)
vis[sg[j]]=1;
for(int l=1;l<=i-2;++l)//枚举左半边个数
{
//i-l-len是右半边个数
for(int len=1;i-l-len>=1;++len)
{
vis[sg[l]^sg[i-l-len]]=1;
}
}
for(int v=0;;++v)
{
if(!vis[v])
{
sg[i]=v;
break;
}
}
}
}
int main()
{
getsg();
while(~scanf("%d",&n))
{
ans=ok=0;
for(int i=0;i<n;++i)
{
int v;
scanf("%d",&v);
ans^=sg[v];
if(sg[v]>1)ok=1;
}
if((!ans&&!ok)||(ans&&ok))puts("Yes");
else puts("No");
}
return 0;
}