正常SG函数为转移的 mex
但是如果我们只能求出他是必胜态还是必败态,异或起来是对的吗?(按照这个思路写了一个,喜提20pts,想知道为啥挂了)
#include<bits/stdc++.h>
using namespace std;
const int N=20;
int f[1<<20|1];//0输1赢
int hv[N+1];
void gt(int x) {
for(int i=19; i>=0; i--)
printf("%d",(x>>i)&1);
printf(" %s\n",f[x]?"WIN":"LOSS");
}
int main() {
// freopen("out.out","w",stdout);
for(int i=0; i<1<<20; i++) {
memset(hv,0,sizeof(hv));
int lst=-1,sum=0;
for(int j=0; j<20; j++) {
if((i>>j)&1) {
hv[20-j]=1;
sum++;
if(lst==-1)continue;
else if(!f[i^(1<<j)^(1<<lst)])f[i]=1;
} else lst=j;
}
int cnt=20-sum+1,ans1=0,tot=0;
for(int i=1; i<=20; ++i) {
if(!hv[i]) {
if((--cnt)&1)ans1^=tot;//奇数级阶梯,异或
tot=0;
} else ++tot; //加棋子到阶梯上
}
// if(i==6){
// puts("have:");
// for(int j=1;j<=20;j++)printf("%d ",hv[j]);puts("");
// }
//// gt(i);
// if((ans1>0&&f[i]==0)||(ans1==0&&f[i]>0)){
// printf("%d ans1:%d",i,ans1);
// return 0;
// }
}
int T;
scanf("%d",&T);
while(T--) {
int n,res=0;
scanf("%d",&n);
for(int i=1; i<=n; i++) {
int t=0,m,x;
scanf("%d",&m);
for(int j=1; j<=m; j++) {
scanf("%d",&x);
t|=1<<20-x;
}
res^=f[t];
}
if(res)puts("YES");
else puts("NO");
}
}
/*
左 001101001 右
*/