HDU-1850-Being a Good Boy in Spring Festival(尼姆博弈)

206 篇文章 0 订阅
78 篇文章 0 订阅

Being a Good Boy in Spring Festival

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5146    Accepted Submission(s): 3085


Problem Description
一年在外 父母时刻牵挂
春节回家 你能做几天好孩子吗
寒假里尝试做做下面的事情吧

陪妈妈逛一次菜场
悄悄给爸爸买个小礼物
主动地 强烈地 要求洗一次碗
某一天早起 给爸妈用心地做回早餐

如果愿意 你还可以和爸妈说
咱们玩个小游戏吧 ACM课上学的呢~

下面是一个二人小游戏:桌子上有M堆扑克牌;每堆牌的数量分别为Ni(i=1…M);两人轮流进行;每走一步可以任意选择一堆并取走其中的任意张牌;桌子上的扑克全部取光,则游戏结束;最后一次取牌的人为胜者。
现在我们不想研究到底先手为胜还是为负,我只想问大家:
——“先手的人如果想赢,第一步有几种选择呢?”
 

Input
输入数据包含多个测试用例,每个测试用例占2行,首先一行包含一个整数M(1<M<=100),表示扑克牌的堆数,紧接着一行包含M个整数Ni(1<=Ni<=1000000,i=1…M),分别表示M堆扑克的数量。M为0则表示输入数据的结束。
 

Output
如果先手的人能赢,请输出他第一步可行的方案数,否则请输出0,每个实例的输出占一行。
 

Sample Input
  
  
3 5 7 9 0
 

Sample Output
  
  
1
 

Author
lcy
 

Source
 

Recommend
lcy   |   We have carefully selected several similar problems for you:   1848  1849  1847  2147  1846 

这道题用了nim游戏的原型(尼姆博弈),只要掌握了尼姆博弈的规律就很好解了!(详见百度百科......)
规定有这样一种比赛,有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
这种情况最有意思,它与二进制有密切关系,我们用(a,b,c)表示某种局势,首先(0,0,0)显然是奇异局势,无论谁面对奇异局势,都必然失败。第二种奇异局势是(0,n,n),只要与对手拿走一样多的物品,最后都将导致(0,0,0)。仔细分析一下,(1,2,3)也是奇异局势,无论对手如何拿,接下来都可以变为(0,n,n)的情形。这种奇异局势也可以称为必败局.(对战双方熟知尼姆博弈的情况下,当前局势为奇异局势,则必败).计算机算法里面有一种叫做按位模2加,也叫做异或的运算,凡是奇异局势(a,b,c),一定满足a^b^c=0(即a异或b异或c=0).对于奇异局势(0,n,n)也一样,结果也是0。注意到异或运算的交换律和结合律,及a^a=0,(a^b)(^)(a^b)=(a^a)(^)(b^b)=0^0=0。
所以程序的思路便是利用了这个技巧!

我们首先求出所有堆异或后的值,再用这个值去对每一个堆进行异或,令res = x1^sum(sum为所有堆的异或值)如果res < x1的话,当前玩家就从x1中取走(x1-res)个,取走x1-res之后这样必然导致对方的堆的异或值为0,也就是奇异局势(必败点),这就是一种方案,遍历每一个堆,进行上面的断判就可以得到总的方案数。


ps:这里想说明一下,为什么res会出现<x1的情况而不是大于x1情况.因为所有堆异或后的值只有两个可能,(1)sum为0.(2)sum不为0.因为要保证先手人赢,counting!(1)sum为0异或任何数都为那个数本身.,此时为奇异局势(必败!res=xi).(2)sum不为0,异或xi之后,此时相当于没有异或xi,即当前值是除了xi的所有异或.所以x1-res之后必然导致奇异局势.即构成方法!

例1。(14,21,39),14(+)21=27,39-27=12,所以从39中拿走12个物体即可达到奇异局势(14,21,27)。
例2。(55,81,121),55(+)81=102,121-102=19,所以从121中拿走19个物品就形成了奇异局势(55,81,102)。
例3。(29,45,58),29(+)45=48,58-48=10,从58中拿走10个,变为(29,45,48)。
例4。我们来实际进行一盘比赛看看:
甲:(7,8,9)->(1,8,9)奇异局势
乙:(1,8,9)->(1,8,4)
甲:(1,8,4)->(1,5,4)奇异局势
乙:(1,5,4)->(1,4,4)
甲:(1,4,4)->(0,4,4)奇异局势
乙:(0,4,4)->(0,4,2)
甲:(0.4,2)->(0,2,2)奇异局势
乙:(0,2,2)->(0,2,1)
甲:(0,2,1)->(0,1,1)奇异局势
乙:(0,1,1)->(0,1,0)
甲:(0,1,0)->(0,0,0)奇异局势
甲胜。
import java.io.*;
import java.util.*;

public class Main
{

	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
		Scanner input = new Scanner(System.in);
		while (input.hasNext())
		{
			int m = input.nextInt();
			if (m == 0)
				break;
			int a[] = new int[m];
			int nim = 0;
			for (int i = 0; i < m; i++)
			{
				a[i] = input.nextInt();
				nim ^= a[i];                       //算出所有堆得异或值
			}
			int sum = 0;
			for (int i = 0; i < m; i++)
			{
				if ((nim ^ a[i]) < a[i])           //如果总异或值与单个堆异或的值小于单个堆则存在方法!
				{
					sum++;
				}
			}
			System.out.println(sum);
		}
	}

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值