博弈的题目,打表找规律还是相当有用的一个技巧。
这个游戏在原始的Nim游戏基础上又新加了一个操作,就是游戏者可以将一堆分成两堆。
这个SG函数值是多少并不明显,还是用记忆化搜索的方式打个表,规律就相当显然了。
1 #include <cstdio> 2 #include <cstring> 3 4 const int maxn = 100; 5 int sg[maxn * 2]; 6 bool vis[maxn * 2]; 7 8 int mex(int v) 9 { 10 if(sg[v] != -1) return sg[v]; 11 memset(vis, false, sizeof(vis)); 12 for(int i = 0; i < v; i++) vis[mex(i)] = true; 13 for(int i = 1; v - i >= i; i++) vis[mex(i) ^ mex(v - i)] = true; 14 for(int i = 0; ; i++) if(!vis[i]) { sg[v] = i; return i; } 15 } 16 17 int main() 18 { 19 memset(sg, -1, sizeof(sg)); 20 sg[0] = 0; 21 for(int i = 0; i < maxn; i++) 22 printf("%d %d ", i, mex(i)); 23 24 return 0; 25 }
1 #include <cstdio> 2 3 inline long long SG(long long x) 4 { 5 if(x == 0) return 0; 6 if(x % 4 == 3) return x + 1; 7 if(x % 4 == 0) return x - 1; 8 return x; 9 } 10 11 int main() 12 { 13 //freopen("in.txt", "r", stdin); 14 15 int T; scanf("%d", &T); 16 while(T--) 17 { 18 int n; scanf("%d", &n); 19 long long ans = 0, x; 20 for(int i = 0; i < n; i++) 21 { 22 scanf("%lld", &x); 23 ans ^= SG(x); 24 } 25 printf("%s ", ans ? "Alice" : "Bob"); 26 } 27 28 return 0; 29 }