题意:n堆石子,每堆a[i]个 每次操作可以从一堆取任意一个,也可以将一堆分为不为0的三堆,最后取完的获胜
思路:简单的SG函数计算。写的比较少,所以这里记录一些笔记
sg(x) =mex{sg(y) : y ∈ F(x)}这个公式的意思, y是x的后继状态,什么是后继状态,简单的说就是x通过一步操作可以到达的状态
公式求的是所有后继状态中第一个没出现的值。
打表后的公式就是
sg[i]=i-1 i%8==0
sg[i]=i+1 i%8==7
sg[i]=i 其他
关键是打表代码
下面是代码和打表代码的合集
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t,n;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
long long ans=0;
long long x;
for(int i=1;i<=n;i++) {
scanf("%lld",&x);
if(x%8==0) {
ans^=(x-1);
continue;
}
if(x%8==7) {
ans^=(x+1);
continue;
}
ans^=x;
}
if(ans) {
printf("First player wins.\n");
}
else {
printf("Second player wins.\n");
}
}
return 0;
}
/**打表找规律**/
/*
int sg[111];
int getsg(int x) {
bool vis[111];
if(sg[x]!=-1) return sg[x];
memset(vis,0,sizeof vis);
vis[0]=1;
for(int i=1;i<x;i++) {
int a=getsg(i);
vis[a]=1;
for(int j=1;j<x-i;j++) {
int b=getsg(j);
int c=getsg(x-i-j);
int tt=a^b^c;
vis[tt]=1;
vis[b]=1;
vis[c]=1;
}
}
for(int i=0;;i++) if(!vis[i]) return i;
}
int main()
{
memset(sg,-1,sizeof sg);
sg[0]=0;sg[1]=1;sg[2]=2;
for(int i=1;i<=100;i++) {
sg[i]=getsg(i);
printf("%d %d\n",i,sg[i]);
}
return 0;
}
*/