关闭

HDU3032->SG函数

标签: hdu
94人阅读 评论(0) 收藏 举报
分类:

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 ;
}
1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:18430次
    • 积分:1467
    • 等级:
    • 排名:千里之外
    • 原创:131篇
    • 转载:4篇
    • 译文:0篇
    • 评论:2条
    最新评论