John(hdu 1907 2509)

11 篇文章 0 订阅

题目:点击打开链接

第2509题也是一模一样的方法

最后一个取的人为输, 即反尼姆,在网上看了很多人写的,感觉有点晕晕乎乎的,然后大神跟我讲了一下,差不多是懂了,趁热赶紧写下来

首先必败局为T, 必胜局为S, 数字代表有几个充裕堆,充裕堆大于或等于2的时候,都写成2 。所以状态总共有T0, S0, S1, S2, T2这五种

注意T1(有一个充裕堆且局面必败)这种情况是不存在的。因为有一个充裕堆的时候局面一定是必胜的,原因是若此时孤单堆堆数为奇数,把充裕堆取完;否则,取成只剩一个。这样,就变成奇数个孤单堆,由对方取,这样你取一个孤单堆,我取一个孤单堆……最终肯定胜。

所以,由上面也可以知道,谁面对S1,谁就胜。

S2只能转换到T2,T2可以转换到S2和S1,所以局面的转化过程必然是S2->T2->S2->T2->  ……  ->T2->S1->S0->T0->……->S0->T0(0)

贴上两个代码,我觉得第一个代码更直观,更能体现思想。

#include <stdio.h>

int main (void)
{
    int n;
    while(scanf("%d", &n) != EOF)
    {
        int a, count = 0, sum = 0;
        int i;
        for(i = 0; i < n; i++)
        {
            scanf("%d", &a);
            sum ^= a;
            if(a > 1)
            	count++;
        }
        if(count == 1)//充裕堆等于1必胜 
        	printf("Yes\n");
        else if(count >= 2 && sum != 0)//充裕堆大于2且异或和不为0必胜 
        	printf("Yes\n");
        else if(count == 0 && sum == 0)//充裕堆为0且是偶数堆必胜 
        	printf("Yes\n");
        else
        	printf("No\n");       
    }
    return 0;
}

还可以总结一下结论就是: 先手胜当且仅当①所有堆石子数都为1且异或和0(即有偶数个孤单堆);②存在某堆石子数大于1且异或和不为0. 下面的代码就是直接根据结论写的。

#include <stdio.h>

int main (void)
{
	int n, t;
	scanf("%d", &t);
	while(t --)
	{
		scanf("%d", &n);
		int a, f = 0, sum = 0;
		int i;
		for(i = 0; i < n; i++)
		{
			scanf("%d", &a);
			sum ^= a;
			if(a > 1)
				f = 1;
		}
		if(f)
		{
			if(sum == 0)
				printf("Brother\n");
			else
				printf("John\n");
		}
		else
		{
			if(sum == 0)
				printf("John\n");
			else
				printf("Brother\n");
		}
	}
	return 0;
}




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值