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