题意:
两人博弈,N堆石子,可以选择移走某一堆的任意数量的石子,也可以选择将这一堆分成任意两堆东西。
思路:和nim游戏差不多,只是多了一个分成两堆的操作,分成两堆也就是计算两个子堆的异或,然后sg函数打表找规律,sg[0]=0,sg[1]=1,2可以变成1+1,1,0,sg[2]=2.....
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 10;
int sg[maxn], vis[maxn];
void init() {
int i, j, k;
sg[0] = 0, sg[1] = 1;
for(i = 2; i <= 1000; i++) {
memset(vis, 0, sizeof(vis));
for(j = 1; j < i; j++)
vis[sg[j]^sg[i - j]] = 1; //拆分
for(j = 0; j < i; j++)
vis[sg[j]] = 1; //取石子
for(j = 0;; j++)
if(!vis[j])
break;
sg[i] = j;
}
for(i = 1; i <= 100; i++)
cout << sg[i] << endl;
}
int main() {
init();
}
然后打表发现如果x%4==0则sg[x]=x-1;
若x%4==1||x%4==2,sg[x]=x;
若x%4==3 ,sg[]=x+1;
然后结论出来了.
#include<bits/stdc++.h>
using namespace std;
#define ll long long;
const int N = 1e6 + 10;
int t, n;
int main() {
cin >> t;
while(t--) {
cin >> n;
int ans = 0;
for(int j, i = 0; i < n; i++) {
cin >> j;
if(j % 4 == 0)
ans ^= (j - 1);
else if(j % 4 == 3)
ans ^= (j + 1);
else
ans ^= j;
}
if(ans)
printf("Alice\n");
else
printf("Bob\n");
}
return 0;
}