2016 Multi-University Training Contest 1 1002 Chess

来源:互联网 发布:网络词香菇是什么意思 编辑:程序博客网 时间:2024/05/23 00:09

题目链接:点击打开链接

题目大意:两个人玩一个游戏,在n*20的棋盘上有若干个棋子,规定每个棋子只能向右移,并且当右边有棋子的时候只能跳过那些棋子,同一个格子只能有一枚棋子,最后不能操作的人胜。

解题思路:算是简单的SG函数求组合博弈的问题,思路早就有了,但是sg函数总是打不对,SG(x)=mex{SG(y)|y是x的后继},mex表示集合中没有出现的最小正整数,将每一组的sg值抑或就可以得到结果。

代码:

#include<iostream>#include<vector>#include<cmath>#include<algorithm>#include<ctime>#include "cstdio"#include "string"#include "string.h"using namespace std;const int maxn = 3e6 + 50;int sg[maxn];int getBit(int x, int i){return ((x >> i) & 1);}int getSuf(int x, int i){x ^= (1 << i);for (int j = i - 1;j >= 0;j--)if (!getBit(x, j))return (x | (1 << j));return -1;}int getSG(int now){//cout << now << endl;if(sg[now]!=-1)return sg[now];int ans = 0;bool vis[20] = { 0 };for (int i = 0;(1 << i) <= now;i++){if (getBit(now, i)){int suf = getSuf(now, i);if (suf == -1)continue;int temp = sg[suf];if (temp == -1){temp = sg[suf] = getSG(suf);}vis[temp] = 1;}}for (int i = 0; ;i++){if (!vis[i]){ans = i;break;}}return sg[now] = ans;}int main(){memset(sg, -1, sizeof(sg));sg[1] = 0;for (int i = (1 << 20);i >= 1;i--)if(sg[i]==-1)sg[i] = getSG(i);int T, n, num, temp;scanf("%d", &T);while (T--){int ans = 0;scanf("%d", &n);while (n--){int now = 0;scanf("%d", &num);for (int i = 0;i < num;i++){scanf("%d", &temp);now |= 1 << (20 - temp);}temp = getSG(now);//cout << temp << endl;ans ^= temp;}if (ans>0)puts("YES");elseputs("NO");}return 0;}


1 0