hdu 5724 Chess(SG函数)
2016-07-23 12:47
381 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5724
题意:给你n*20的棋盘,然后每行上面都有些棋子,在一行上,对于一个棋子,你可以把它移动到右边最近的一个空格上(可以跳过其他棋子),最后不能移动的人输,给你状态,问你先手的输赢
题解:博弈题,考虑到有n行,所以应该是n个游戏的nim和,只要把每行的状态的SG函数都求出来,最后异或即可。我SG函数忘的差不多了,写了个递推,以为是SG函数,然后异或,一直wa,后来才想起来,递推是处理单个游戏的时候,SG[i]=mex(S)表示i这个状态的后继状态的SG值里最小的未出现的值。这就是SG定理,加上这题转移状态不超过20,直接暴力跑就行了。
详细过程看代码。
题意:给你n*20的棋盘,然后每行上面都有些棋子,在一行上,对于一个棋子,你可以把它移动到右边最近的一个空格上(可以跳过其他棋子),最后不能移动的人输,给你状态,问你先手的输赢
题解:博弈题,考虑到有n行,所以应该是n个游戏的nim和,只要把每行的状态的SG函数都求出来,最后异或即可。我SG函数忘的差不多了,写了个递推,以为是SG函数,然后异或,一直wa,后来才想起来,递推是处理单个游戏的时候,SG[i]=mex(S)表示i这个状态的后继状态的SG值里最小的未出现的值。这就是SG定理,加上这题转移状态不超过20,直接暴力跑就行了。
详细过程看代码。
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; #define MAX 1000005 #define MAXN 6005 #define maxnode 15 #define sigma_size 30 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define middle int m=(r+l)>>1 #define LL long long #define ull unsigned long long #define mem(x,v) memset(x,v,sizeof(x)) #define lowbit(x) (x&-x) #define pii pair<int,int> #define bits(a) __builtin_popcount(a) #define mk make_pair #define limit 10000 //const int prime = 999983; const int INF = 0x3f3f3f3f; const LL INFF = 0x3f3f; const double pi = acos(-1.0); //const double inf = 1e18; const double eps = 1e-8; const LL mod = 998244353LL; const ull mx = 133333331; /*****************************************************/ inline void RI(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; } /*****************************************************/ int sg[2222222]; int vis[25]; void init(){ sg[0]=0; for(int i=(1<<20)-1;i>=0;i--){ mem(vis,0); for(int j=0;j<20;j++){ if((i>>j)&1){ for(int k=j+1;k<20;k++){ if(!((i>>k)&1)){ vis[sg[i^(1<<j)^(1<<k)]]=1; break; } } } } for(int j=0;;j++){ if(!vis[j]){ sg[i]=j; break; } } } } int main(){ int t; cin>>t; init(); while(t--){ int n; cin>>n; int ans=0; for(int i=0;i<n;i++){ int m; scanf("%d",&m); int tmp=0; for(int j=0;j<m;j++){ int a; scanf("%d",&a); tmp|=(1<<(a-1)); } ans^=sg[tmp]; } if(ans) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }
相关文章推荐
- hdu 1005
- 交叉引用的解决方法——类声明的应用
- 微软要干掉点对点 Skype,Linux 和 Mac 原生客户端将消亡
- Docker1.12 + Swarm 构建动态微服务应用
- Docker1.12 + Swarm 构建动态微服务应用
- 一个简单的代码计算行数demo编写
- PCB_Layout中的3W和20H原则以及在allegro中的实现方法
- JSP基础知识及工程创建
- 设计模式——状态模式
- 【CodeForces 261B】Maxim and Restaurant(DP,期望)
- 基于sklearn几种分类算法
- 【linux工具使用】无法使用ssh 登录ubuntu16.04的问题解决方案(root账户)
- linux的vm相关参数介绍
- 软件测试基础(二)---黑盒测试案例设计技术
- mongo3.x ssl版安装文件
- 通过nfs挂载共享目录的方式搭建lamp平台并安装wordpress(二)
- 矩阵的frobenius范数及其求偏导法则
- 哈哈哈哈哈哈
- [CTS]PhoneNumberUtilsTest-- testGetMethods&&ManagedProfileTest-- testManagedContacts
- 小希的礼物