发现很多时候可以从打表中找SG函数的规律。
此题如果没有分割这个操作其实就是简单是异或一下就好了(其实就是SG函数)
多的这个操作想到与考虑后继状态 sg(x + y ) 。我们知道sg(x + y ) 可以从 sg(x) ^ sg(y) 求出。于是可以尝试先打表出sg函数。
int vis[105]; int sg[105]; void init() { for (int i = 0; i <= 100; i++) { memset(vis, 0, sizeof vis); for (int j = 1; j <= i; j++) vis[sg[i - j]] = 1; for (int j = 1; j < i; j++) vis[sg[j] ^ sg[i - j]] = 1; for(int j = 0;;j++) if (!vis[j]) { sg[i] = j; break; } } for (int i = 0; i <= 100; i++) cout << i << " " << sg[i] << " "; }
发现和4有关。
int get_sg(int x) { if (x % 4 == 0) return x - 1; else if (x % 4 == 1 || x % 4 == 2) return x; else return x + 1; }
于是对所有堆sg异或一下就好了。
int main() { //init(); int T = readint(); while (T--) { int n = readint(); int res = 0; for (int i = 0; i < n; i++) { int x = readint(); res ^= get_sg(x); } if (!res) puts("Bob"); else puts("Alice"); } }