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. P1090 合并果子(哈弗曼树)

    题目描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和.可 ...

  2. [BUUOJ记录] [GXYCTF2019]BabySQli

    有点脑洞的题,题目不难,主要考察注入和联合查询的一个小特点 进入题目是一个登录框,看看源代码,在search.php文件中发现了这个 大写的字母和数字很明显是base32,先用base32解码一下,发 ...

  3. C# 获取当前月的月初和月末

    /// <summary> /// 获取当前月的月末日期 /// </summary> /// <returns></returns> public s ...

  4. 剑指 Offer 44. 数字序列中某一位的数字

    题目描述 数字以0123456789101112131415-的格式序列化到一个字符序列中.在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等. 请写一个函数,求任意第n位 ...

  5. 跟着尚硅谷系统学习Docker-【day08】

    day08-20200723   p32.docker 安装redis   [ docker pull redis] [docker run -p 6397:6397 -v /tmp/mydocker ...

  6. [oracle/sql]写SQL从学生考试成绩三表中选出五门分综合超过720的尖子

    任务:有学生,科目,考分三张表,需要从中筛选出五门考分总和超过720的学生. 科目表最简单只有五条记录: CREATE TABLE tb_course ( id NUMBER not null pri ...

  7. leetcode刷题-79单词搜索

    题目 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格.同一个单元格内的字母不允许被重复 ...

  8. python日志模块配置

    import logging logging.basicConfig(filename= 'out.log',filemode= 'w+', level= logging.DEBUG, format= ...

  9. Python3实现zip分卷压缩

    Python实现zip分卷压缩 使用 zipfile 库 查看 官方中文文档 利用 Python 压缩 ZIP 文件,我们第一反应是使用 zipfile 库,然而,它的官方文档中却明确标注" ...

  10. 利用预编译解决C/C++重复定义的错误 -2020.09.13

    利用预编译解决C/C++重复定义的错误 -2020.09.13 我们现在有main.c和function.h两个文件 main.c #include <stdio.h> #include ...