HDU 5724 Chess

因为一行最多只有20个数,也就是说只有(1<<20)种状态,向右移动表示小的数推向了大的数。可以用SG函数预处理出所有情况。然后把每一行的SG函数值异或一下,非零则必胜,否则输。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;

int sg[1<<21];
bool h[25];

void init_SG()
{
    memset(sg,0,sizeof sg);
    for(int i=(1<<20)-1;i>=0;i--)
    {
        memset(h,0,sizeof h);
        for(int j=0;j<20;j++)
        {
            if((i&(1<<j))==0) continue;
            for(int k=j+1;k<20;k++)
            {
                if((i&(1<<k))!=0) continue;
                h[sg[i-(1<<j)+(1<<k)]]=1; break;
            }
        }
        for(int j=0;j<=20;j++) if(h[j]==0) { sg[i]=j; break; }
    }
}

int main()
{
    init_SG();
    int T; scanf("%d",&T);
    while(T--)
    {
        int n; scanf("%d",&n);
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            int k,y=0; scanf("%d",&k);
            while(k--)
            {
                int f; scanf("%d",&f); f--;
                y=y|(1<<f);
            }
            ans=ans^sg[y];
        }
        if(ans) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

 

posted @ 2016-07-21 22:20  Fighting_Heart  阅读(279)  评论(0编辑  收藏  举报