HDU3032->SG函数
题意:
两个人玩游戏,有n堆石子,每堆个数不等,可以进行的操作是从任一堆中取任意颗石子,或者把这堆石子分成两堆。
给出一个初始的局面,判断先手胜还是后手胜。
题解:
sg(n)代表从当前状态到游戏结束最多需要多少步
当有n堆石子时,游戏相当于一个组合博弈,当前的sg值就是每堆石子的sg值异或的结果。
对于任意的一个 Anti-SG 游戏,如果我们规定当局面中所有单一游戏的 SG 值为 0 时游戏 结束,则先手必胜当且仅当以下两个条件满足任意一个:
(1)游戏的 SG 函数不为 0,且游戏中某个单一游戏的 SG 函数大于1。
(2)游戏的 SG 函数为 0,且游戏中没有单一游戏的 SG 函数大于 1。
很明显:sg(0) = 0,sg(1) = 1。
状态2的后继有:0,1和(1,1),他们的SG值分别为0,1,0,所以sg(2) =2。
状态3的后继有:0、1、2、(1,2),他们的SG值分别为0、1、2、3,所以sg(3) = 4。
状态4的后继有:0、1、2、3、(1,3)和(2,2),他们的SG值分别为0,1,2,4,5,0,所以sg(4) = 3.
打表可以发现规律:
if(x%4==0) sg[x]=x-1;
if(x%4==1||x%4==2) sg[x]=x;
if(x%4==3) sg[x] = x+1。
代码:
#include <stdio.h>
#include <iostream>
using namespace std ;
int main()
{
int T , n , m;
int res ;
scanf("%d" , &T) ;
while(T --)
{
scanf("%d" , &n) ;
res = 0 ;
while(n --)
{
scanf("%d" , &m) ;
if(m%4 == 0) res^=(m - 1) ;
if(m%4==1||m%4==2) res^=m ;
if(m%4==3) res^=(m+1) ;
}
if(res == 0) printf("Bob\n") ;
else printf("Alice\n") ;
}
return 0 ;
}