题目链接
先学习一下基础的理论知识,here
按照里面的理论,就可以做了
SG定理,以及2个关于必胜,必败状态的定理
必胜状态:存在一种走法走到一个必败状态。
必败状态:后继状态都为必胜状态。
找SG值,一般是 找规律,打表,递推,动态规划等方法
本题按照定理,递推出就可以了
#include<bits/stdc++.h>
using namespace std;
#define cl(a,b) memset(a,b,sizeof(a))
#define LL long long
#define pb push_back
#define gcd __gcd
const int maxn = 1e5+200;
const int inf = 1 << 23;
int grundy[(1<<20)+200];
void solve(){
for(int i=0;i<(1<<20);i++){
//set<int> s;//计算当前的状态i一步可以转移到的状态的grundy值
int s[35];cl(s,-1);
for(int j=0;j<20;j++){
if((i&(1<<j))){
for(int k=j-1;k>=0;k--)if((i&(1<<k))==0){//k找到右边的空格
//s.insert(grundy[i^(1<<j)^(1<<k)]);break;
s[grundy[i^(1<<j)^(1<<k)]]=1;break;
}
}
}
int ret=0;
while(s[ret]!=-1)ret++;
grundy[i]=ret;
}
}
int main(){
//cout<<(1<<20)<<endl; equ = 1048576
solve();
int T;scanf("%d",&T);
while(T--){
int ans=0;
int n;scanf("%d",&n);
while(n--){
int k;scanf("%d",&k);
int s = 0;
while(k--){
int x;scanf("%d",&x);
s|=(1<<(20-x));
}
ans^=grundy[s];
}
if(!ans){
puts("NO");
}
else {
puts("YES");
}
}
return 0;
}