E - Misere Nim(反nim博弈,最后一手拿石子的输)


思路:一般的nim博弈大家都会吧,一般的就是取最后一枚石子的人赢;

先讨论 n 堆石子全部为1的情况:

当 n 为奇数时,先手一定输,后手一定赢

当 n 为偶数时,先手一定赢,后手一定输;

当 n堆 不全部为1的情况:

我们先看一般的nim博弈的必胜态:当前状态为必胜态,先手经最优策略 取过后,就到达必败态也就是平衡态,平衡态只能转移到不平衡态(必胜态),不平衡态经过 某一个途径 可以 转移到平衡态;

当n堆 不全部为1时,当一般的nim博弈的必胜态也就是不一样的nim博弈的必胜态,当前状态为 不平衡态;

先手                 后手             先手                              先手                     后手                          先手

不平衡态 —> 平衡态 —> 不平衡态 —> …–> 不平衡态 —> 不平衡态(下面有解释) --> 平衡态–>

 必胜态            必败态          必胜态                          必胜态               必败态                 必胜态

解释:在这些从 不平衡态 到 平衡态 的 转中,在不一样的nim博弈中,有一个临界情况,一定会出现 从不平衡态到不平衡态,后面这个不平衡态 是 (剩下奇数堆且这奇数堆石子数全部都是1),当前这个状态取的人一定输,也是就后手,所以先手一定赢;具体看代码理解

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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;
}

你可能感兴趣的:(博弈论)