BZOJ1188 [HNOI2007]分裂游戏(SG定理)
2015-06-07 23:22
211 查看
注意:
1. 位运算的优先级低于"=="
2. vis[]的大小不一定等于n,具体多大需实验得知
3. 初始化的问题
4. Nim游戏中SG函数的意义:对于,某状态先手的胜负情况,必败状态的SG==0,必胜状态SG!=0,
组合游戏的SG为所有子游戏SG的xor和,独立游戏的SG为:排除所有后继状态的SG 的最小非负整数
本题中,将某个未知的数减少1,其后的某两个位置(可能重叠)值增加1
堆与堆之间存在转化关系,故不能将每一堆看作一个独立游戏,
而同一堆中,所有石子相互独立,可以将每个石子的移动看成一个独立游戏
SG[i]表示:移动第i堆的任意一个石子 先手的胜负情况
显然只有最后一对的石子无后继状态,即SG[n-1]=0
其他的可以递推得出:假设i<j<=k,i的一个后继状态为(j+k)的组合状态,故 SG[i]的取值要排除 SG[j]^SG[k]
那么整个游戏的SG为:所有石子的SG和。注意 不是所有堆的SG和,因为作为独立游戏的是单个石子而非整堆
xor有一个性质:a xor a == 0,所以 每堆石子只需xor一次(含奇数个石子),或不xor(含偶数个石子)
求第一步时枚举i,j,k,能使先手进行后,后手进入必败状态,就可以计入答案
代码
1. 位运算的优先级低于"=="
2. vis[]的大小不一定等于n,具体多大需实验得知
3. 初始化的问题
4. Nim游戏中SG函数的意义:对于,某状态先手的胜负情况,必败状态的SG==0,必胜状态SG!=0,
组合游戏的SG为所有子游戏SG的xor和,独立游戏的SG为:排除所有后继状态的SG 的最小非负整数
本题中,将某个未知的数减少1,其后的某两个位置(可能重叠)值增加1
堆与堆之间存在转化关系,故不能将每一堆看作一个独立游戏,
而同一堆中,所有石子相互独立,可以将每个石子的移动看成一个独立游戏
SG[i]表示:移动第i堆的任意一个石子 先手的胜负情况
显然只有最后一对的石子无后继状态,即SG[n-1]=0
其他的可以递推得出:假设i<j<=k,i的一个后继状态为(j+k)的组合状态,故 SG[i]的取值要排除 SG[j]^SG[k]
那么整个游戏的SG为:所有石子的SG和。注意 不是所有堆的SG和,因为作为独立游戏的是单个石子而非整堆
xor有一个性质:a xor a == 0,所以 每堆石子只需xor一次(含奇数个石子),或不xor(含偶数个石子)
求第一步时枚举i,j,k,能使先手进行后,后手进入必败状态,就可以计入答案
代码
#include<stdio.h> #include<stdlib.h> int p[25],SG[25],vis[55]; void getSG(int n) { int i,j,k; for(i=0;i<=50;i++) vis[i]=-1; SG[n-1]=0; for(i=n-2;i>=0;i--) { for(j=i+1;j<n;j++) for(k=j;k<n;k++) vis[SG[j]^SG[k]]=i; for(j=0;vis[j]==i;j++); SG[i]=j; } } int main() { int T,n,i,j,k,ans,tot; scanf("%d",&T); for(;T>0;T--) { scanf("%d",&n); for(i=0;i<n;i++) scanf("%d",&p[i]); getSG(n); ans=tot=0; for(i=0;i<n;i++) if(p[i]&1) ans^=SG[i]; for(i=0;i<n;i++) for(j=i+1;j<n;j++) for(k=j;k<n;k++) { if((ans^SG[i]^SG[j]^SG[k])==0) { tot++; if(tot==1) printf("%d %d %d\n",i,j,k); } } if(tot>0) printf("%d\n",tot); else printf("-1 -1 -1\n0\n"); } return 0; }
相关文章推荐
- 第一篇文章
- Hello JavaScript!
- 【Android UI设计与开发】第06期:底部菜单栏(一)使用TabActivity实现底部菜单栏
- spring+hibernate:在applicationCOntext.XML中配置C3P0参数说明Attempted to use a closed or broken resource pool
- RBAC权限设计实例
- Linux CC攻击脚本
- 团队项目--设计类图
- rabbitmq method之basic.consume
- 设计模式那点事--单例模式
- 4.7.6  使用 new 来创建动态数组
- BZOJ246 [中山市选2009]谁能赢呢?(讨论奇偶性)
- 图书管理系统类图
- php 正则表达式使用
- 数据库水平切分的实现原理解析---分库,分表,主从,集群,负载均衡器
- 进程间通信方式
- HDU 5264 pog loves szh I (字符串,水)
- nginx-tomcat负载均衡redis-session共享,静态资源分离
- Android 开发中常用的Animation
- [设计模式]_[观察者模式在窗口之间消息传递的使用例子]
- IQ测试结果