sdnuoj1251题目链接
比赛的时候混淆了博弈论的规则,感觉这个题的规则不伦不类的,又像威佐夫博弈又像尼姆博弈的,没想到真的是这个样子,比赛的时候题目中第二个规则的最后一条没有看到,还有就是没有用到素数的提示,导致思路全无,后来自己想的时候,发现可以分开做,即n==2的时候就是威佐夫博弈,当n不等于二的时候,规则像极了尼姆博弈,于是就想,尼姆博弈面对奇异局势之时,即所有数异或结果为0时,此时先手之人必定不会只选择一堆(白白等死),他一定会尝试同时取多堆石子(万一有救呢对吧。。),于是问题来了,取多堆石子的目的是完成必败态到必败态的转变,能不能成功呢,没思路了
于是想看看有没有人写题解,百度了一下,发现这居然是第八届省赛的a题,师哥只是改了改主人公的名字而已。。。大佬找到了两个我没想到的地方
1.除2以外的素数都是奇数
2.必败态时每堆石子二进制对应位数必定是 奇数个0 + 偶数个1(不难发现其实)
这样在取石子的时候,必定会有所有石子某一位全部取反,取反之后该位对应着 奇数个1 + 偶数个0,异或结果必定非0,即无法实现由必败态到必败态的转变(还是要等死),而当奇数堆变为偶数堆的时候(某一堆取完),第二个条件的第二部分无法使用,总结一下就是普通又扯淡的尼姆博弈!!
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
using namespace std;
int a[35];
int main()
{
int t;
int n;
scanf("%d",&t);
while(t --)
{
scanf("%d",&n);
int ans = 0;
for(int i = 1; i <= n; i ++){
scanf("%d",&a[i]);
ans ^= a[i];
}
if(n == 2)//威佐夫博弈
{
double w = (sqrt(5) + 1) / 2;
if(a[1] > a[2]) swap(a[1], a[2]);
int k = w * (a[2] - a[1]);
if(k == a[1]) printf("Bob\n");
else printf("Alice\n");
}
else//尼姆博弈
{
//int ans = 0;
if(ans) printf("Alice\n");
else printf("Bob\n");
}
}
return 0;
}