来源:HDU5726
多校的一道博弈题,SG函数,打表取抑或,关键是如何打表
代码:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 20;
int sg[(1<<N)+10];//状态压缩
int vis[20];//由于求MEX函数
int mex(int x){//对于一个状态x
int i,k=-1;
memset(vis,false ,sizeof(vis));
for(int i=0;i<N;i++){
if(!((1<<i)&x))//从小开始找,x状态下
k=i;
else if(k!=-1)
vis[sg[x^(1<<k)^(1<<i)]] = true;
}
for(i=0;i<N;i++)//mex函数定义
if(!vis[i]) return i;
}
void getSG(){
sg[0]=0;
for(int i=1;i<(1<<N);i++){
sg[i]=mex(i);
}
}
int main(){
int T;
getSG();
scanf("%d",&T);
while(T--){
int n,cnt,ans,s;
scanf("%d",&n);
ans=0;
for(int i=0;i<n;i++){
scanf("%d",&cnt);
s=0;
for(int j=0;j<cnt;j++){
int d;
scanf("%d",&d);
s+=(1<<(N-d));//状态记录为S
}
ans^=sg[s];//NIM
}
if(ans) puts("YES");
else puts("NO");
}
return 0;
}