HDU 3032 Nim or not Nim?(sg函数博弈)

来源:互联网 发布:国内医疗纠纷数据统计 编辑:程序博客网 时间:2024/05/23 01:12

题目地址:HDU 3032

这题是很好用来练习sg函数打表的一题。

下面是sg函数值打表代码:

#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <stdlib.h>#include <math.h>#include <ctype.h>#include <queue>#include <map>#include <set>#include <algorithm>using namespace std;#define LL long longint sg[110000];//sg函数值打表代码int getsg(int x){    int ans, i;    int mex[11000];    memset(mex,0,sizeof(mex));    for(i=x-1; i>=0; i--)//当选择拿出石子时的sg后继标记    {        mex[sg[i]]=1;    }    for(i=1; i<=x/2; i++)//当选择分成两堆时的sg后继标记    {        ans=0;        ans^=sg[i];        ans^=sg[x-i];        mex[ans]=1;    }    for(i=0;; i++)//最小的非sg后继数    {        if(!mex[i])        {            sg[x]=i;            return sg[x];        }    }}int main(){    int t, n, x, sum, i;    sg[0]=0;    for(i=0; i<100; i++)    {        getsg(i);        printf("sg[%d]->%d\n",i,sg[i]);    }    return 0;}

由输出结果可以看出来

sg[4k]=4k-1

sg[4k+1]=4k+1;

sg[4k+2]=4k+2;

sg[4k+3]=4k+4;

所以可以直接根据这个规律来判断所有情况下的sg值了。然后从头到尾异或过去就可以解出来了。

代码如下:

#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <stdlib.h>#include <math.h>#include <ctype.h>#include <queue>#include <map>#include <set>#include <algorithm>using namespace std;#define LL long longint main(){    int t, n, x, sum, i;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        sum=0;        for(i=0;i<n;i++)        {            scanf("%d",&x);            if(x%4==0) sum^=x-1;            else if(x%4==1||x%4==2) sum^=x;            else sum^=x+1;        }        if(sum) puts("Alice");        else puts("Bob");    }    return 0;}


1 0
原创粉丝点击