LUOGU P2575 高手过招

传送门

解题思路

博弈论,发现每一行只有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;
}

猜你喜欢

转载自blog.csdn.net/qq_40448823/article/details/81335627