HDU1907John(尼姆博弈-先取光者输)

大佬的讲解:http://blog.csdn.net/fsss_7/article/details/51374659


链接:http://acm.hdu.edu.cn/showproblem.php?pid=1907

题意:有n个装有若干糖果的盒子,有两个人轮流拿糖果,只能在一个盒子中拿,至少拿一个糖果最多可拿掉整盒。拿完最后一次的人输

分析:经典的Nim博弈的一点变形。设糖果数为1的叫孤独堆,糖果数大于1的叫充裕堆,设状态S0:a1^a2^..an!=0&&充裕堆=0,则先手必败(奇数个为1的堆,先手必败)。S1:充裕堆=1,则先手必胜(若剩下的n-1个孤独堆个数为奇数个,那么将那个充裕堆全部拿掉,否则将那个充裕堆拿得只剩一个,这样的话先手必胜)。T0:a1^a2^..an=0&&充裕堆=0,先手必胜(只有偶数个孤独堆,先手必胜)。S2:a1^a2^..an!=0&&充裕堆>=2。T2:a1^a2^..an=0&&充裕堆>=2。这样的话我们用S0,S1,S2,T0,T2将所有状态全部表示出来了,并且S0先手必败,S1、T0先手必胜,那么我们只需要对S2和T2的状态进行分析就行了。(a)S2可以取一次变为T2。(b)T2取一次可变为S2或者S1。因为S1是先手必胜态,那么根据a,b这两个转换规则,我们就能得知S2也是先手必胜,T2是先手必败。


#include<bits/stdc++.h>
using namespace std;
int main()
{
    int T, n, s, sum, a;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        s = sum = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &a);
            s ^= a;
            if(a > 1)
                sum++;
        }
        if((sum == 0 && n & 1) || (!s && sum >= 2))
            printf("Brother\n");
        else
            printf("John\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值