BZOJ1022(SHOI2008)[小约翰的游戏John]--博弈论(反Nim游戏)

【链接】
bzoj1022

【题目大意】

反Nim游戏。

【解题报告】

假设 sum 是所有数的 xor 值。

(1)、每堆都是 1

所以当sum=0时,先者必胜,否则后者胜。

(2)、如果有两个堆且有堆里的个数不为 1 ,其他都为1

若先者拿走一堆,那么后者可以选择将另一堆留下 1 个或者全拿走,所以后者必胜;

若先者将一堆拿剩一个,那么后者可以选择将另一堆留下一个让先者拿或全拿走,所以后者必胜;

若先者将一堆拿走一部分,那么后者可以将另一堆同样拿走一部分,然后同上

由以上状态大概可以推知

如果所有堆全是1 , sum=0 先者必胜 否则后者必胜

如果有堆不是 1 , sum=0后者必胜 否则先者必胜

#include<cstdio>
#include<cstring>
using namespace std;
int T,n;
inline char nc()
{
    static char buf[100000],*l,*r;
    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
    if (l==r) return EOF; return *l++;
}
inline int Read()
{
    int res=0; char ch=nc();
    while (ch<'0'||ch>'9') ch=nc();
    while (ch>='0'&&ch<='9') res=res*10+ch-48,ch=nc();
    return res;
}
void Work()
{
    n=Read();int sum=0; int flg=0;
    for (int i=1; i<=n; i++)
    {
        int x=Read(); sum^=x;
        if (x^1) flg=1;
    }
    if ((flg&&sum)||(!flg&&!sum)) printf("John"); else printf("Brother"); putchar(10);
}
int main()
{
    freopen("1022.in","r",stdin);
    freopen("1022.out","w",stdout);
    T=Read();
    while (T--) Work();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值