BZOJ 1188 [HNOI2007]分裂游戏 SG函数
2015-08-03 15:26
543 查看
题意:链接
方法: SG函数
解析:挺有思维量的题?不要D我
这道题关键在于局面与子游戏的把握。如何定义这道题的局面呢?
想了半个小时没有想出来,因为毕竟如果令石子数的话是会与其他游戏产生干扰的。
然后看了某神犇的题解?定义局面:一颗豆子在i位置处。
一下子恍然大悟啊,YY一下就AC了。
现在考虑一个局面:一颗豆子在i位置。
会有什么子游戏呢?会转移到一颗豆子在j位置以及一颗豆子在k位置。
而一颗豆子在i位置时的sg[i]怎么算呢?就是其所有子游戏的mex运算。而子游戏是什么呢?是一颗豆子在j以及一颗豆子在k两个子局面的异或和。所以我们能算出sg[i]。
假设i这个位置有一堆豆子,那我们需要将sg[i]异或一堆遍。所以可以有一个优化,一个位置的豆子数为奇数时,只需要异或一次,为偶数时不需要异或。
n的范围小的令人发指,所以我们可以枚举第一步。
第一步过后能使得总局面的sg值为0的话即我们操作之后对于另一人来说,该人必败,统计一下方案数就OK了。
代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 25 #define M 10010 using namespace std; int a ; int ssgg ; int t,n; int sg(int x) { if(x==n)return 0; if(ssgg[x]!=-1)return ssgg[x]; int v[M]; memset(v,0,sizeof(v)); for(int i=x+1;i<=n;i++) { for(int j=i;j<=n;j++) { v[sg(i)^sg(j)]=1; } } for(int i=0;;i++)if(!v[i])return ssgg[x]=i; } int ai,bi,ci; int main() { scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); memset(ssgg,-1,sizeof(ssgg)); int tmp=sg(1);ssgg =0; int cnt=0; for(int i=1;i<=n;i++) { if(a[i]!=0) { for(int j=i+1;j<=n;j++) { for(int k=j;k<=n;k++) { a[i]--,a[j]++,a[k]++; int ans=0; for(int l=1;l<=n;l++) { if(a[l]&1) ans^=ssgg[l]; } if(ans==0) { cnt++; if(cnt==1) { printf("%d %d %d\n",i-1,j-1,k-1); } } a[i]++,a[j]--,a[k]--; } } } } if(!cnt)printf("-1 -1 -1\n"); printf("%d\n",cnt); } }
相关文章推荐
- Multiplication algorithm
- 利用Attribute和IErrorHandler处理WCF全局异常
- 94.Binary Tree Inorder Traversal(二叉树先序遍历)
- Snail—iOS开发中得一些小技巧
- S5P4418 GPS+北斗移植
- jmeter在window和linux环境下的执行
- rpc学习1-基本概念
- HDU 2048 神、上帝以及老天爷(错排)
- 深入理解DIP、IoC、DI以及IoC容器
- utf-8、utf8、UTF-8
- ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using passwor
- 倒油问题详解 (深搜、广搜)(面向过程和面向对象)
- slf4j绑定log4j失败
- qualcomm platform camera porting
- 文章标题
- Java 反射机制中 getMethod()和getDeclaredMethod()区别
- 获取命令帮助
- HashMap原理
- git使用记录
- Emag eht htiw Em Pleh(POJ--2993