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; }