题意:
给你n堆石子,你每次只能操作一堆石子
1、拿去任意个,最少1个
2、把这一堆分成两堆,没有要求对半分
解析+代码:
1 //解题思路: 2 //对于一个给定的有向无环图,定义关于图的每个顶点的Sprague-Grundy函数g如下:g(x)=mex{ g(y) | y是x的后继 },这里的g(x)即sg[x] 3 //例如:取石子问题,有1堆n个的石子,每次只能取{1,3,4}个石子,先取完石子者胜利,那么各个数的SG值为多少? 4 //sg[0]=0, 5 //n=1时,可以取走{1}个石子,剩余{0}个,mex{sg[0]}={0},故sg[1]=1; 6 //n=2时,可以取走{1}个石子,剩余{1}个,mex{sg[1]}={1},故sg[2]=0; 7 //n=3时,可以取走{1,3}个石子,剩余{2,0}个,mex{sg[2],sg[0]}={0,0},故sg[3]=1; 8 //n=4时,可以取走{1,3,4}个石子,剩余{3,1,0}个,mex{sg[3],sg[1],sg[0]}={1,1,0},故sg[4]=2; 9 //n=5时,可以取走{1,3,4}个石子,剩余{4,2,1}个,mex{sg[4],sg[2],sg[1]}={2,0,1},故sg[5]=3; 10 //以此类推..... 11 // x 0 1 2 3 4 5 6 7 8.... 12 //sg[x] 0 1 0 1 2 3 2 0 1.... 13 //所以,对于这题: 14 //sg[0]=0 15 //sg[1]=mex{sg[0] }=1 16 //sg[2]=mex{sg[0],sg[1],sg[1,1] }=mex{0,1,1^1}=2; 17 //sg[3]=mex{sg[0],sg[1],sg[2],sg[1,2]}=mex{0,1,2,1^2}=mex{0,1,2,3}=4; 18 //sg[4]=mex{sg[0],sg[1],sg[2],sg[3],sg[1,3],sg[2,2]}=mex{0,1,2,4,5,0}=3; 19 // .............................................................................. 20 // 21 //可以发现:sg[4*k+1]=4*k+1,sg[4*k+2]=4*k+2, sg[4*k+3]=4*k+4,sg[4*k+4]=4*k+3 22 //通过SG函数打表可以发现规律。 23 //当n=4*k时,sg[n] = n-1; 24 //当n= 4*k+3 时,sg[n] = n+1; 25 //其余sg[n] = n; 26 #include <stdio.h> 27 #include <algorithm> 28 #include <iostream> 29 #include <string.h> 30 using namespace std; 31 const int MAXN = 10000; 32 int SG(int x) 33 { 34 if(x == 0)return x; 35 if(x % 4 == 0)return x-1; 36 if(x % 4 == 3)return x+1; 37 return x; 38 } 39 int main() 40 { 41 int T; 42 int n,a; 43 int sum; 44 scanf("%d",&T); 45 while(T--) 46 { 47 scanf("%d",&n); 48 sum = 0; 49 for(int i = 0;i < n;i++) 50 { 51 scanf("%d",&a); 52 sum ^= SG(a); 53 } 54 if(sum == 0)printf("Bob "); 55 else printf("Alice "); 56 } 57 return 0; 58 }