Link

题面

题目描述

小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有 \(n\) 堆石子,小约翰和他的哥哥轮流取石子,每个人取的时候,可以随意选择一堆石子,

在这堆石子中取走任意多的石子,但不能一粒石子也不取,我们规定取到最后一粒石子的人算输。小约翰相当固执,他坚持认为先取的人有很大

的优势,所以他总是先取石子,而他的哥哥就聪明多了,他从来没有在游戏中犯过错误。小约翰一怒之前请你来做他的参谋。

自然,你应该先写一个程序,预测一下谁将获得游戏的胜利。

输入格式

本题的输入由多组数据组成,第一行包括一个整数 \(T\)(1≤T≤500),表示输入总共有 \(T\) 组数据。

每组数据的第一行包括一个整数 \(N\)(1≤N≤50),表示共有 \(N\) 堆石子,接下来有 \(N\) 个不超过 5000 的整数,分别表示每堆石子的数目。

输出格式

对于每组数据,如果约翰能赢得比赛,则输出 John,否则输出 Brother,请注意单词的大小写。

输入输出样例

输入 #1

2

3

3 5 1

1

1

输出 #1

John

Brother

说明/提示

对于 40% 的数据,T≤250

对于 100% 的数据,T≤500

题解

裸的Anti_nim 板子题。

Anti_nim 和普通的 nim 游戏的区别是取走最后一个的人输。

我们定义一下几种状态

T 态 亦或和为0

S 态 亦或和不为0

孤单堆 一堆仅有一个火柴

充裕堆 一堆有大于等于一根的火柴

T0 态 T态中充裕堆为0的状态

T2 态 T态中充裕堆数大于等于二的状态

S0 态 S态中充裕堆数位0的状态

S1 态 S态中充裕堆数为一的状态

S2 态 S态中充裕堆数大于等于二的状态

注:没有T1态,因为因为只有一个充裕堆时 其最高位对应>1 不会被异或消掉,也就是充裕堆会影响高位

引理1:

S0态必败,T0态必胜

这个就和普通的 nim 游戏一样

引理2:

S1态必胜

1.孤单堆为奇数时,拿走充裕堆就变成了 S0态

2.孤单堆为偶数时,那就把充裕堆拿成孤单堆,在重复情况1

引理3:

S2态不可能转化为 T0态

因为S2态至少有两个充裕堆,取一次最多减少一个充裕堆,但T0态没有一个充裕堆,所以不符合题意。

引理4:

S2态只要方法正确,可以一次性变成T2态。

S2态不能变成T0 态,又没有 T1 态,

又根据 S态能转化为 T 态,所以 S2 态只能转化为 T2 态

引理5

T2态只能转化为 S1态和S2态

首先T2不能转化为 S0态,因为两个充裕堆你没法一起取走。

假设我们T2态有两个充裕堆,取走一个就变成了一个也就是S1态。

有大于二个充裕堆时,取走之后充裕堆数大于等于一也就是 S2态。

引理6

S2态必胜

  1. 先手把S2态变成T2态

  2. 后手只能把T2态变为S1或S2态,变为S1态后手必败,先手必胜。变为S2态,先手可以重复步骤一。

所以S2态必胜

引理7

T2态必败

T2态只能转化为 S1态和 S2态,但那两个都是必胜态,所以T2必败

必胜态 T0,S1,s2

必败态 S0,T2

观察规律发现

1.每一堆石子只有一个时 且异或和为0
2.存在至少一堆石子多于一个时 且异或和不为0

先手必胜

SJ定理

定义 Anti_nim

决策集合为空时 当前者胜,其余同SG游戏

先手胜利,当且仅当

1.游戏SG函数不为0且某个单一游戏SG值大于1

2.游戏SG函数为0且任意单一游戏SG值=1

然后,这道题就变成了模板题

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int T,n,ans,cnt1,cnt2,num[55];
inline int read()
{
int s = 0,w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
return s * w;
}
int main()
{
T = read();
while(T--)
{
n = read(); ans = 0; cnt1 = 0, cnt2 = 0;
for(int i = 1; i <= n; i++)
{
num[i] = read();
ans ^= num[i];
if(num[i] > 1) cnt1++;
}
// cout<<ans<<" "<<cnt1<<endl;
if(ans == 0 && cnt1 == 0) printf("John\n");
if(ans != 0 && (cnt1 == 1 || cnt1 >= 2)) printf("John\n");
if(ans != 0 && cnt1 == 0) printf("Brother\n");
if(ans == 0 && cnt1 >= 2) printf("Brother\n");
}
return 0;
}

P4279 [SHOI2008]小约翰的游戏(Anti_nim)的更多相关文章

  1. 洛谷 P4279 [SHOI2008]小约翰的游戏 解题报告

    P4279 [SHOI2008]小约翰的游戏 题目描述 小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有\(n\)堆石子,小约翰和他的哥哥轮流取石子,每个人取的时候,可以随意选择一堆石子,在这堆石子 ...

  2. BZOJ 1022 Luogu P4279 [SHOI2008]小约翰的游戏 (博弈论)

    题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=1022 (luogu) https://www.luogu.org/pro ...

  3. P4279 [SHOI2008]小约翰的游戏

    嘟嘟嘟 一道博弈论经典题,nim游戏. 只不过要考虑有奇数个石子为1的堆的时候,为Brother赢.剩下就是nim游戏了. 极简代码 #include<cstdio> using name ...

  4. bzoj 1022: [SHOI2008]小约翰的游戏John anti_nim游戏

    1022: [SHOI2008]小约翰的游戏John Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1189  Solved: 734[Submit][ ...

  5. SHOI2008小约翰的游戏John

    1022: [SHOI2008]小约翰的游戏John Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1139  Solved: 701[Submit][ ...

  6. BZOJ 1022 [SHOI2008]小约翰的游戏John

    1022: [SHOI2008]小约翰的游戏John Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1635  Solved: 1036[Submit] ...

  7. 1022: [SHOI2008]小约翰的游戏John

    1022: [SHOI2008]小约翰的游戏John Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1322  Solved: 829[Submit][ ...

  8. 1022: [SHOI2008]小约翰的游戏John【Nim博弈,新生必做的水题】

    1022: [SHOI2008]小约翰的游戏John Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2709  Solved: 1726[Submit] ...

  9. bzoj千题计划112:bzoj1022: [SHOI2008]小约翰的游戏John

    http://www.lydsy.com/JudgeOnline/problem.php?id=1022 http://www.cnblogs.com/TheRoadToTheGold/p/67448 ...

随机推荐

  1. 【Android】Listview返回顶部,快速返回顶部的功能实现,详解代码。

    作者:程序员小冰,GitHub主页:https://github.com/QQ986945193 新浪微博:http://weibo.com/mcxiaobing 首先给大家看一下我们今天这个最终实现 ...

  2. MonoBehaviour生命周期与对象数据池应用

    预热游戏对象: tempObject = Instantiate(cubePrefab) as GameObject ; tempObject .SetActive( false ); 游戏对象tem ...

  3. steam 数据转换

    目录 数组和集合互转 数组转集合 方法一 遍历 方法二 asList 方法三 steam 集合转数组 方法一 循环 方法二 toArray 方法三 steam 小结 string转为Character ...

  4. 【干货满满】1.5w字初中级前端面试复习总结

    前言 金九银十,又是一波跑路.趁着有空把前端基础和面试相关的知识点都系统的学习一遍,参考一些权威的书籍和优秀的文章,最后加上自己的一些理解,总结出来这篇文章.适合复习和准备面试的同学,其中的知识点包括 ...

  5. 高可用服务之Keepalived基础入门

    前面我们聊了聊高可用集群corosync+pacemaker的相关概念以及相关工具的使用和说明,回顾请参考https://www.cnblogs.com/qiuhom-1874/category/18 ...

  6. Activiti7 组任务

    需求:在流程定义中在任务节点的assignee固定设置任务负责人,这种情况不是很好,如果有天任务负责人请假了,你想请假,等着吧..没人审批,针对这种情况,可以给任务设置多个候选人,可以从候选中选择参与 ...

  7. Oracle快速建表Sample

    表定义: create table tb_triple( id number(8,0) primary key, name nvarchar2(20), birthday date ) 充值: ins ...

  8. SpringIOC初始化过程--详解

    SpringIOC初始化过程 相信大家都知道Spring这个东西,我们经常来用他一些特性,比如说他的AOP,IOC,那今天就带大家解析下SpringIOC的加载过程. 我们来看一个例子 Annotat ...

  9. Ubuntu更换国内源--解决终端下载速度慢的问题

    目前我已知的更改国内源的方法基本上就两种,第一种,把/etc/apt/sources.list文件里的源更换一下,改成阿里云或者其它源.第二种,更换在设置中software&updates(软 ...

  10. Git | Git入门,成为项目管理大师(一)

    大家好,周一我们迎来了一个新的专题--git. 写这个专题的初衷有两点,第一点是觉得好像很少有公众号提到git相关的技术,可能是觉得太基础了看不上.但实际上git非常重要,在我们实际的开发工作当中使用 ...