思路:一般的nim博弈大家都会吧,一般的就是取最后一枚石子的人赢;
先讨论 n 堆石子全部为1的情况:
当 n 为奇数时,先手一定输,后手一定赢
当 n 为偶数时,先手一定赢,后手一定输;
当 n堆 不全部为1的情况:
我们先看一般的nim博弈的必胜态:当前状态为必胜态,先手经最优策略 取过后,就到达必败态也就是平衡态,平衡态只能转移到不平衡态(必胜态),不平衡态经过 某一个途径 可以 转移到平衡态;
当n堆 不全部为1时,当一般的nim博弈的必胜态也就是不一样的nim博弈的必胜态,当前状态为 不平衡态;
先手 后手 先手 先手 后手 先手
不平衡态 —> 平衡态 —> 不平衡态 —> …–> 不平衡态 —> 不平衡态(下面有解释) --> 平衡态–>
必胜态 必败态 必胜态 必胜态 必败态 必胜态
解释:在这些从 不平衡态 到 平衡态 的 转中,在不一样的nim博弈中,有一个临界情况,一定会出现 从不平衡态到不平衡态,后面这个不平衡态 是 (剩下奇数堆且这奇数堆石子数全部都是1),当前这个状态取的人一定输,也是就后手,所以先手一定赢;具体看代码理解
#include <iostream>
#include <algorithm>
#include <cmath>
#include <ctype.h>
#include <cstring>
#include <cstdio>
#include <sstream>
#include <cstdlib>
#include <iomanip>
#include <string>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int maxn=1000000;
const ll mod = 1e9+7;
int main(){
int t;
int cas=1;
scanf("%d",&t);
while(t--)
{
int m,sum=0;
scanf("%d",&m);
int flag=0,x;
for(int i = 0;i < m;i ++)
{
scanf("%d",&x);
if(x != 1)
flag = 1;
sum ^= x;
}
printf("Case %d: ",cas++);
if(!flag)
{
if(m&1) printf("Bob\n");
else printf("Alice\n");
}
else
{
if(sum) printf("Alice\n");
else printf("Bob\n");
}
}
return 0;
}