传送门:HDU 5724
题意:n×20的棋盘内放置了一些棋子,每颗棋子走到向右的最近的空格(可以跳过其他棋子)为一次操作,Alice先手,问谁会赢。
思路:由于每行长度只有20,因此我们可以状压预处理出所有状态的sg函数,然后对输入的每一行的状态的sg值异或起来就好了。
代码:
#include<bits/stdc++.h>
using namespace std;
bool vis[22];
int sg[1 << 21];
void init()
{
int up = 1 << 20;
for(int sta = 0; sta < up; sta++)
{
memset(vis, 0, sizeof(vis));
for(int i = 19; i >= 0; i--)
{
if(sta & 1 << i)
for(int j = i - 1; j >= 0; j--)
{
if(!(sta & 1 << j))
{
int tmp = sta;
tmp |= (1 << j);
tmp &= ~(1 << i);
vis[sg[tmp]] = 1;
break;
}
}
}
for(int i = 0; i < 20; i++)
if(!vis[i])
{
sg[sta] = i;
break;
}
}
}
int main()
{
int T, n, m, tmp, t, ans;
init();
cin >> T;
while(T--)
{
ans = 0;
scanf("%d", &n);
while(n--)
{
scanf("%d", &m);
tmp = 0;
while(m--)
{
scanf("%d", &t);
tmp |= 1 << (20 - t);
}
ans ^= sg[tmp];
}
if(ans)
cout << "YES\n";
else
cout << "NO\n";
}
}