解题思路
博弈论,发现每一行只有1<<20的状态,可以把每个状态的sg函数算出来,然后将所有的都异或起来即为答案。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int T,n,m,sg[(1<<20)+5],ans,nxt;
bool vis[25];
inline void Get_SG(int x){
memset(vis,false,sizeof(vis));nxt=0;
for(register int i=1;i<=20;i++){
if(x&(1<<i-1)){
if((x&(1<<i-2))==0 && i>=2) vis[sg[x^(1<<i-1)^(1<<i-2)]]=1;
else if(nxt) vis[sg[x^(1<<i-1)^(1<<nxt-1)]]=1;
}
else nxt=i;
}
int tot=0;
while(vis[tot]) tot++;
sg[x]=tot;
}
int main(){
for(register int i=0;i<1<<20;i++) Get_SG(i);
T=rd();
while(T--){
n=rd();ans=0;
for(register int i=1;i<=n;i++) {
m=rd();int S=0;
for(register int j=1;j<=m;j++) {
int x=rd();
S+=(1<<(20-x));
}
ans^=sg[S];
}
puts(ans?"YES":"NO");
}
return 0;
}