BZOJ 1022 [SHOI2008]小约翰的游戏John
1022: [SHOI2008]小约翰的游戏John
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 1635 Solved: 1036
[Submit][Status][Discuss]
Description
小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不取,我们规定取到最后一粒石子的人算输。小约翰相当固执,他坚持认为先取的人有很大的优势,所以他总是先取石子,而他的哥哥就聪明多了,他从来没有在游戏中犯过错误。小约翰一怒之前请你来做他的参谋。自然,你应该先写一个程序,预测一下谁将获得游戏的胜利。
Input
本题的输入由多组数据组成,第一行包括一个整数T,表示输入总共有T组数据(T≤500)。每组数据的第一行包括一个整数N(N≤50),表示共有N堆石子,接下来有N个不超过5000的整数,分别表示每堆石子的数目。
Output
每组数据的输出占一行,每行输出一个单词。如果约翰能赢得比赛,则输出“John”,否则输出“Brother”,请注意单词的大小写。
Sample Input
3
3 5 1
1
1
Sample Output
Brother
HINT
【数据规模】
对于40%的数据,T ≤ 250。
对于100%的数据,T ≤ 500。
Source
题解:系统的学了一下博弈论。。。妈妈呀。。。
具体去膜贾志豪的集训队论文好了。。。
对于这道题,zidaneandmessi:
①石子数全是1的时候,是最简单的情况。堆数为奇数后手必胜,为偶数先手必胜。
②只有两堆石子数不为1,且它们的石子数相等,后手必胜,理由如下:
(1)先手若取走一堆,后手可以取走另一堆或者剩下一个,回到状态①。
(2)先手若取一堆剩一个,后手可以取走另一堆或剩一个,回到状态①。
(3)先手若取一堆剩下多于一个,后手可以在另一堆中取走相同个数的石子,重复状态②(3),直到两堆都只剩两个石子,先手必须选择②(1)或②(2)。
③只有两堆石子数不为1,且它们的石子数不相等。先手必胜。先手可以从多的一堆里取,使两堆石子相等,回到状态②。
④剩下偶数堆,由多对相等且不为1的石子堆组成。后手必胜。无论先手如何取,后手都在配对的堆中取相同个数的石子,这样可以使相等的堆两两消去,最后转为状态②。
⑤剩下偶数堆。由同样的多对不相等且不为1的石子堆组成。后手必胜。后手可以用③的方法每次使配对的两堆石子数相等,转为状态④。
⑥剩下部分是同样的多对不相等且不为1的石子堆,其余堆石子数都相等。
(1)相等的堆数为偶数,后手必胜。后手可以按⑤的方法转到状态②获胜。
(2)相等的堆数为奇数,先手必胜。先手从相等的拿走一堆后就变成了⑥(1)。
行了,就此打住!如果再这么写下去,恐怕是无止境了。写到这里,我们发现后手总是尽可能地制造配对,并想方设法地回到他最擅长的状态②。但是知道了这个并没有多大用处,因为对于抽象的问题,还是无法下手。
但是我们发现了,如果能配对成功,a1^a2^...^an=0这个等式确实是成立的,因为以异或运算满足交换律和结合律,把配对的两个异或结果算出之后,就全变成0了。
如果a1^a2^...^an结果不为0呢?那么后手就倒霉了。因为先手总能找出一种拿石子的方式,把异或变成0。设结果为x,则每一个ai异或x后肯定有增有减,不可能全都增加。至少,为结果x提供最高位1的那个ai异或x后最高位变0了,一定是减少的。只要先手把它拿成剩下x个,新局面的异或结果就是0了。
那么后手有没有翻盘的可能呢?答案是否定的。因为一旦异或结果变成0后,再拿只会让异或结果不再是0。因为如果两次都是0了,设这次拿走石子把ai=m变成了ai=n(0<n<m),a1^a2^…^a(i-1)^a(i+1)^…^an的运算结果设为s,则s^n=0,s^m=0,说明n=m=s,与n<m矛盾,这样后手不论再怎么拿,都不能避免失利。
另外,如果结果为0,但是不能配对怎么办?很简单,根据上面的结论异或结果为0和不为0是交替变化的,只要先手每次移动使结果不为0,后手就再让结果为0就可以了,这样下去直到石子剩得不多了,胜负就很明显了。所以,后手一旦失误,先手就会使局势扭转!看似随意的游戏,实际上步步为营啊!
还没完,我们推导了半天把孤零零的状态①给忘了。注意到②有个条件是相等两堆石子数不为1,所以如果所有石子数都是1,直接套用①的结论即可。
代码们:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#define PAU putchar(' ')
#define ENT putchar('\n')
using namespace std;
inline int read(){
int x=,sig=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')sig=-;ch=getchar();}
while(isdigit(ch))x=*x+ch-'',ch=getchar();
return x*=sig;
}
inline void write(int x){
if(x==){putchar('');return;}if(x<)putchar('-'),x=-x;
int len=,buf[];while(x)buf[len++]=x%,x/=;
for(int i=len-;i>=;i--)putchar(buf[i]+'');return;
}
void init(){
int x,t,n,T;bool f=true;
T=read();
while(T--){
n=read();f=true;t=;
for(int i=;i<=n;i++){
x=read();
if(x!=)f=;
t^=x;
}
if(f&&(n&))puts("Brother");
else if(f)puts("John");
else if(t)puts("John");
else puts("Brother");
}
return;
}
void work(){
return;
}
void print(){
return;
}
int main(){init();work();print();return ;}
BZOJ 1022 [SHOI2008]小约翰的游戏John的更多相关文章
- bzoj 1022: [SHOI2008]小约翰的游戏John anti_nim游戏
1022: [SHOI2008]小约翰的游戏John Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1189 Solved: 734[Submit][ ...
- BZOJ 1022 [SHOI2008]小约翰的游戏John AntiNim游戏
1022: [SHOI2008]小约翰的游戏John Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1475 Solved: 932[Submit][ ...
- BZOJ 1022: [SHOI2008]小约翰的游戏John (Anti-nim)
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3134 Solved: 2003[Submit][Status][Discuss] Descripti ...
- BZOJ 1022: [SHOI2008]小约翰的游戏John【anti-SG】
Description 小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不取 ...
- BZOJ 1022 SHOI2008 小约翰的游戏John 博弈论
题目大意:反Nim游戏,即取走最后一个的人输 首先状态1:假设全部的堆都是1,那么堆数为偶先手必胜,否则先手必败 然后状态2:假设有两个堆数量同样且不为1,那么后手拥有控场能力,即: 若先手拿走一堆, ...
- BZOJ 1022: [SHOI2008]小约翰的游戏John [SJ定理]
传送门 $anti-nim$游戏,$SJ$定理裸题 规定所有单一游戏$sg=0$结束 先手必胜: $1.\ sg \neq 0,\ 某个单一游戏sg >1$ $2.\ sg = 0,\ 没有单一 ...
- BZOJ.1022.[SHOI2008]小约翰的游戏John(博弈论 Anti-Nim)
题目链接 Anti-Nim游戏: 先手必胜当且仅当: 1.所有堆的石子数为1,且异或和为0 2.至少有一堆石子数>1,且异或和不为0 简要证明: 对于1:若异或和为1,则有奇数堆:异或和为0,则 ...
- 51nod 1069 Nim游戏 + BZOJ 1022: [SHOI2008]小约翰的游戏John(Nim游戏和Anti-Nim游戏)
首先,51nod的那道题就是最简单的尼姆博弈问题. 尼姆博弈主要就是判断奇异局势,现在我们就假设有三个石子堆,最简单的(0,n,n)就是一个奇异局势,因为无论先手怎么拿,后手总是可以在另一堆里拿走相同 ...
- bzoj 1022: [SHOI2008]小约翰的游戏John【anti-nim】
如果全是1,那么n是奇数先手必败 否则,xor和为0先手必败 证明见 https://www.cnblogs.com/Wolfycz/p/8430991.html #include<iostre ...
随机推荐
- Linux下得到显示屏参数的方法
先安装一个软件,然后使用权ddcprobe可以查看当前支持的分辨率和刷新频率#sudo apt-get install xresprobe运行 #sudo ddcprobe会得到下面的信息vbe: V ...
- common-httpclient 用户名密码认证示例
import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.com ...
- iOS网络HTTP、TCP、UDP、Socket 知识总结
OSI 七层模型 我们一般使用的网络数据传输由下而上共有七层,分别为物理层.数据链路层.网络层.传输层.会话层.表示层.应用层,也被依次称为 OSI 第一层.第二层.⋯⋯. 第七层. 如下图: 各层功 ...
- .NET六大剑客:栈、堆、值类型、引用类型、装箱和拆箱
.NET六大剑客:栈.堆.值类型.引用类型.装箱和拆箱 一.“堆”,“栈”专区 这两个字我相信大家太熟悉了,甚至于米饭是什么?不知道...“堆”,“栈”是什么?哦,这个知道... 之前我也写过一篇堆栈 ...
- DataTable数据与Excel表格的相互转换
using Excel = Microsoft.Office.Interop.Excel; private static Excel.Application m_xlApp = null; /// & ...
- 使用Javascript限制文本框只允许输入数字
很多时候需要用到限制文本框的数字输入,试过许多方法,都不太理想,遂决定自己实现一个来玩玩.曾经使用过的方法通过onkeydown事件来控制只允许数字: <input onkeydown=&quo ...
- jquery获取元素到屏幕底的可视距离
jquery获取元素到屏幕底的可视距离 要打对号的图里的height(我自称为可视高度:滚动条未滑到最底端) 不是打叉图里的到页面底部(滚动条到最底部时的height)(offset().top方法 ...
- DontDestroyOnLoad
本文由博主(YinaPan)原创,转载请注明出处:http://www.cnblogs.com/YinaPan/p/Unity_DontDestroyOnLoad.html public stati ...
- cocos2dx lua调用C++类.
最近需求所迫, 终于着手传说中的 lua 了. 折腾了4天, 总算大概搞明白了用法. 细节咱们就别谈了, 直接说项目里怎么跑起来. 准备工作 我们需要一系列繁琐的前奏. tolua++: 这是必备工具 ...
- js 实现win7任务栏拖动效果
前言 在某个时刻, 我认识了一个朋友. 此人在我的教唆下, 踏上了js的不归路. 前天他问我, Win7任务栏拖动效果怎么实现. 我随口就跟他说, 这简单的一逼. 在我一晚上的折腾之后, 一份潦草的代 ...