[博弈论]洛谷P2575(有向图游戏的和)

https://www.luogu.com.cn/problem/P2575

题意:

100%的数据T≤100,n≤1000,m≤20,1≤pj≤20

思路:
状态压缩dp
每一行是一个游戏
最终的答案是每行的sg值异或起来
计算每一行时,当前状态的sg值 = mex{后继状态的sg值}
用vis存后继状态的sg,求mex

细节:
从每行的最后一个从后往前,用last0记录最后一个是0的位置

代码

const int N=2e5+10,M=1<<21;
int t,n,m;
int sg[M];
int dfs(int x){
    if(sg[x] != -1) return sg[x];
    int vis[20];
    memset(vis,0,sizeof vis);
    int last0 = -1;
    for(int i=19;i>=0;i--){
        if((x >> i) & 1){
            if(last0 != -1)
                vis[dfs(x ^ (1 << i) ^ (1 <<last0))] = 1;//先抵消第i个,再将last0的位置填上
        }else{
            last0 = i;
        }
    }
    for(int i=0;i<20;i++){
        if(!vis[i]) return sg[x] = i;
    }
}
int main(){
    memset(sg,-1,sizeof sg);
    read(t);
    while(t--){
        read(n);
        int res = 0;
        while(n--){
            read(m);
            int cnt = 0;
            for(int i=1;i<=m;i++){
                int x;
                read(x);
                x--;
                cnt |= (1 << x);
            }
            res ^= dfs(cnt);
        }
        if(res) puts("YES");
        else puts("NO");
    }
    return 0;
}
posted @ 2021-06-29 23:27  Isaac233  阅读(109)  评论(0)    收藏  举报