题目地址: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 long int 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 long int 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; }
HDU 3032 Nim or not Nim?(sg函数博弈)
原文地址:http://blog.csdn.net/scf0920/article/details/39323471