1. 程式人生 > >HDU 1850 Being a Good Boy in Spring Festival(Nim博弈)

HDU 1850 Being a Good Boy in Spring Festival(Nim博弈)

問題描述

Being a Good Boy in Spring Festival

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

Problem Description

一年在外 父母時刻牽掛春節回家 你能做幾天好孩子嗎寒假裡嘗試做做下面的事情吧陪媽媽逛一次菜場悄悄給爸爸買個小禮物主動地 強烈地 要求洗一次碗某一天早起 給爸媽用心地做回早餐如果願意 你還可以和爸媽說咱們玩個小遊戲吧

ACM課上學的呢~下面是一個二人小遊戲:桌子上有M堆撲克牌;每堆牌的數量分別為Ni(i=1…M);兩人輪流進行;每走一步可以任意選擇一堆並取走其中的任意張牌;桌子上的撲克全部取光,則遊戲結束;最後一次取牌的人為勝者。現在我們不想研究到底先手為勝還是為負,我只想問大家:——“先手的人如果想贏,第一步有幾種選擇呢?

Input

輸入資料包含多個測試用例,每個測試用例佔2行,首先一行包含一個整數M(1<M<=100),表示撲克牌的堆數,緊接著一行包含M個整數Ni(1<=Ni<=1000000i=1…M),分別表示M堆撲克的數量。M0則表示輸入資料的結束。

Output

如果先手的人能贏,請輸出他第一步可行的方案數,否則請輸出0,每個例項的輸出佔一行。

Sample Input

3

5 7 9

0

Sample Output

1

------------------------------------------------------------

思路

Nim博弈。定義“局勢”為各堆撲克牌數量的組合,例如(5,7,9)表示第一堆有5個,第二堆有7個,第三堆有9個。定義“奇異局勢”為先手必敗的局勢,顯然(0,0,0)就是奇異局勢。於是Nim博弈判勝負問題歸結為給定局勢判斷是否是奇異局勢。

定理:局勢(a[1], a[2], …, a[k])是奇異局勢的條件是 a[1] ^ a[2] ^ … ^ a[k] = 0.(^為異或運算)

此題要求給定局勢,求可以變成奇異局勢的方法數。注意到 a^a=0, 因此轉化為判斷k個數中k-1個相異或,所得結果與餘下一個數比較大小的問題。

------------------------------------------------------------

程式碼

#include<cstdio>

int a[105];

int main()
{
	int n, i, j, b, cnt = 0;
	while (scanf("%d", &n))
	{
		if (n == 0)
		{
			break;
		}
		cnt = 0;
		for (i = 0; i < n; i++)
		{
			scanf("%d", a + i);
		}
		for (i = 0; i < n; i++)
		{
			b = 0;
			for (j = 0; j < n; j++)
			{
				if (i != j)
				{
					b ^= a[j];
				}
			}
			if (a[i] > b)
			{
				cnt++;
			}
		}
		printf("%d\n", cnt);
	}
	return 0;
}