首页 > 代码库 > hdu 3032(博弈sg函数)

hdu 3032(博弈sg函数)

题意:与原来基本的尼姆博弈不同的是,可以将一堆石子分成两堆石子也算一步操作,其它的都是一样的。

分析:由于石子的堆数和每一堆石子的数量都很大,所以肯定不能用搜索去求sg函数,现在我们只能通过找规律的办法求得sg的规律。

通过打表找规律可以得到如下规律: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<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

int sg[1000];


int calsg(int x)
{
    int next[105],i,flag;
    memset(next,0,sizeof(next));
    
    for(i=1;i<=x/2;i++)
    {
        flag=sg[i]^sg[x-i];
    //    printf("%d %d\n",sg[i],sg[x-i]);
        next[flag]=1;
    }

    for(i=1;i<=x;i++)
    {
        if(sg[x-i]==-1)
            sg[x-i]=calsg(x-i);
        next[sg[x-i]]=1;
    }

    for(i=0; ;i++)
        if(next[i]==0)
            return i;
}


int main()
{
    int i;
    memset(sg,-1,sizeof(sg));
    sg[0]=0;sg[1]=1;
    //sg[2]=2;
    printf("0\n1\n");
    for(i=2;i<=100;i++)
    {
        sg[i]=calsg(i);
        printf("%d\n",sg[i]);
    }

    return 0;
}

ac代码:

#include<stdio.h>
#include<string.h>
#include<math.h>

int n;

int main()
{
    int T,i,res,x;
    scanf("%d",&T);
    while(T--)
    {
        res=0;
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            scanf("%d",&x);
            if(x%4==0)
                res=res^(x-1);
            else if(x%4==1||x%4==2)
                res=res^(x);
            else
                res=res^(x+1);
        }
        if(res!=0)
            printf("Alice\n");
        else
            printf("Bob\n");
    }
    return 0;
}