博弈是不公平的游戏 因为只要双方足够聪明 从游戏开始就已经确定了结果
在我们的博弈游戏中 想获取胜利 就要寻找必输状态
要寻找必败状态 首先要知道什么情况下算输
在游戏规则下 轮到你了却无法进行操作 就认定为输了(这是游戏的前提)
然后 我们寻找必败态
想一下 如果你面对必败态 那么你做任何操作 都将会把局面转化为非必败态(如果你能转化为必败态 你对手岂不是输了~~~~~那你就不是必败了)
那么你只能转化为非必败态 你的对手面对非必败态一定可以将其转化为必败态(这样才能保证你必败~~)
综上 --在一个存在必输局面和必赢策略的游戏中 一定满足以下性质
1、非必败态一定可以移动到必败态;
2、在必败态做的所有操作的结果都是非必败态。
(不是官方的定义 我自己总结的 帮助理解 如有不足 欢迎指正)
那么我们找到的必败态 最起码要满足这两个性质。
条件:
n 个物品堆成一堆。两个人轮流从这堆物品中取,规定每次至少取一个,最多取 m 个。最后取光者得胜。(无法取者败)
正解:
n大于m时 如果 n%(m+1)≠0 先手必胜
原理:
我们证明下 n%(m+1)=0 先手必败
当轮到你拿的时候 如果 n是(m+1)的倍数 我们称这种情况为奇异局 就是必败局
简单想一下 比如 有n=6 m=5 每次最多拿5个 你拿不完 而且不管你拿几个 对手都可以拿完 取得胜利
而n=(m+1)*k时 是一样的 每次不管你怎么拿 你都不能保持局面是(m+1)的倍数(这就满足了必败态的性质2)
而你的对手每次都可以拿走几个保持局面是 (m+1)的倍数(满足了必败态的性质1)
所以 n%(m+1)=0 先手必败 不是(m+1)的倍数的时候 你只要拿走几个让局面变成奇异局就好了
条件:
威佐夫博弈(Wythoff's game):有两堆各若干个物品,两个人轮流从任一堆取至少一个或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
正解:
面对奇异局势先手必输。
如何判断是不是奇异局势:给你(a,b) a
k=b-a 如果 a =[k(1+√5)/2],b= a + k (方括号表示取整) 就是奇异局势
解释:
我们用(a[k],b[k])(a[k] ≤ b[k] ,k=0,1,2,...,n)(表示两堆物品的数量并称其为局势,如果甲面对(0,0),那么甲已经输了,如果甲面对(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)都可以推出甲必输。这一串数有什么规律呢
(ai,bi) ai是前面未出现过的最小整数。bi=ai+k; k呢是这一串数的序号 第一个是0 然后是1 2 3.。。
同时k也是这几对数每对数(a,b)的差值
这是我们找到的规律 是否就是我们要找的奇异局势也就是必输局面呢
我们证明一下
证明之前 我们先观察我们发现的规律
很容易发现它有一个性质
任何自然数都包含在一个且仅有一个奇异局势中。
ai是前面未出现过的最小整数。bi=ai+k;由这两个规律, 从数学上可以证明此性质。
然后再看满足我们说的规律的数 是否满足必败态的性质
满足性质1、非必败态一定可以移动到必败态;
面对(a,b)一对数,只有 相等和不相等两种情况。不管相等还是不相等,根据刚才提到的性质,都必然有一个数属于一个奇异局势,而我们只要对另一个数进行减法操作就可以使它变为奇异局势。(主要是因为性质:.每个数,必然存在它对应的奇异局势。)我们很容易变到奇异局势。
满足性质2、在必败态做的所有操作的结果都是非必败态。
根据性质1,若只改变奇异局势(a[k],b[k])的某一个分量,那么另一个分量不可能出现在其他奇异局势中,所以必然是非奇异局势。如果使(a[i],b[i])的两个分量同时减少,则由于其差不变,且不可能是其他奇异局势的差,因此也是非奇异局势。(每个奇异局势的差是唯一的)
所以符合我们规律的就是我们要找的必败局面 奇异局势
那么我们只要判断出符合我们找到的规律就行
bi=ai+k; k是(ai,bi)的差值 但是ai不好找
我们进一步发现规律 ai=[k*1.618]方括号代表取整。(0.618是黄金分割数,但是我们写代码不能写0.618,因为后边还有小数需要精确,所以我们写 (1+sqrt(5) )/2
1.618=(1+sqrt(5))/2
所以 结论是如果a =[k(1+√5)/2],b= a + k (方括号表示取整) 就是奇异局势
代码
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
int T,n,m,a,b;
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
a=min(m,n);b=max(m,n);
int k=b-a;
if(a==(int)( k*( 1+sqrt(5) )/2 ) )printf("B\n");
else printf("A\n");
}
return 0;
}
有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
正解
每堆物品的数量进行异或运算 结果等于0 就是奇异局势 就是必败态
原理
我们用(a,b,c)表示某种局势,首先(0,0,0)显然是奇异局势,无论谁面对奇异局势,都必然失败。第二种奇异局势是(0,n,n),只要与对手拿走一样多的物品,最后都将导致(0,0,0)。仔细分析一下,(1,2,3)也是奇异局势,无论对手如何拿,接下来都可以变为(0,n,n)的情形。
这些局势都满足 a^b^c=0
而异或运算法则是 相同为0 不同为1 根据运算法则 面对奇异局你不论怎么拿 都不会还=0(满足性质2)
而不满足的a^b^c=0的局势 我们都可以使其变成a^b^c=0
因为 局面(a,b,c) 我们只要令最大的数 比如是a 令a=b+c 就变成了 (b+c)^b^c=(b^b)+(c^c)=0(满足性质1)
所以 a^b^c=0就是i我们要找的奇异局势 必败状态