HDU3032->SG函数

来源:互联网 发布:知乎 如何练宽 编辑:程序博客网 时间:2024/05/21 10:16

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 ;}
0 0
原创粉丝点击