取石子问题
有一种很有意思的游戏,就是有物体若干堆,可以是火柴棍或是围棋子等等均可。两个人轮流从堆中取物体若干,规定最后取光物体者取胜。这是我国民间很古老的一个游戏,别看这游戏极其简单,却蕴含着深刻的数学原理。下面我们来分析一下要如何才能够取胜。
(一)巴什博奕(Bash Game):只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个。最后取光者得胜。
<wbr><wbr><wbr>显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜。因此我们发现了如何取胜的法则:如果n=(m+1)r+s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后取者拿走k(≤m)个,那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的取法,那么先取者肯定获胜。总之,要保持给对手留下(m+1)的倍数,就能最后获胜。</wbr></wbr></wbr>
即,若n=k*(m+1),则后取着胜,反之,存在先取者获胜的取法。
n%(m+1)==0. 先取者必败。
<wbr><wbr><wbr>这个游戏还可以有一种变相的玩法:两个人轮流报数,每次至少报一个,最多报十个,谁能报到100者胜。</wbr></wbr></wbr>
从一堆100个石子中取石子,最后取完的胜。
(二)威佐夫博奕(Wythoff Game):有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
<wbr><wbr><wbr>这种情况下是颇为复杂的。我们用(ak,bk)(ak ≤ bk ,k=0,1,2,...,n)表示两堆物品的数量并称其为局势,如果甲面对(0,0),那么甲已经输了,这种局势我们称为奇异局势。前几个奇异局势是:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。<br><wbr><wbr><wbr>可以看出,a0=b0=0,ak是未在前面出现过的最小自然数,而 bk= ak + k,奇异局势有<br>
如下三条性质:<br><br><wbr><wbr><wbr>1。任何自然数都包含在一个且仅有一个奇异局势中。<br><wbr><wbr><wbr>由于ak是未在前面出现过的最小自然数,所以有ak > ak-1 ,而 bk= ak + k > ak-1 + k-1 = bk-1 > ak-1 。所以性质1。成立。<br><wbr><wbr><wbr>2。任意操作都可将奇异局势变为非奇异局势。<br><wbr><wbr><wbr>事实上,若只改变奇异局势(ak,bk)的某一个分量,那么另一个分量不可能在其他奇异局势中,所以必然是非奇异局势。如果使(ak,bk)的两个分量同时减少,则由于其差不变,且不可能是其他奇异局势的差,因此也是非奇异局势。<br><wbr><wbr><wbr>3。采用适当的方法,可以将非奇异局势变为奇异局势。<br><br><wbr><wbr><wbr>假设面对的局势是(a,b),若 b = a,则同时从两堆中取走 a 个物体,就变为了奇异局势(0,0);如果a = ak ,b > bk,那么,取走b - bk个物体,即变为奇异局势;如果 a = ak , b < bk ,则同时从两堆中拿走 ak - ab - ak个物体,变为奇异局势( ab - ak , ab - ak+ b - ak);如果a > ak ,b= ak + k,则从第一堆中拿走多余的数量a - ak 即可;如果a < ak ,b= ak + k,分两种情况,第一种,a=aj
(j < k),从第二堆里面拿走 b - bj 即可;第二种,a=bj (j < k),从第二堆里面拿走 b - aj 即可。<br><br><wbr><wbr><wbr>从如上性质可知,两个人如果都采用正确操作,那么面对非奇异局势,先拿者必胜;反之,则后拿者取胜。<br><br><wbr><wbr><wbr>那么任给一个局势(a,b),怎样判断它是不是奇异局势呢?我们有如下公式:<br><wbr><wbr><wbr>ak =[k(1+√5)/2],bk= ak+ k (k=0,1,2,...,n 方括号表示取整函数)<br>
奇妙的是其中出现了黄金分割数(1+√5)/2 = 1。618...,因此,由ak,bk组成的矩形近似为黄金矩形,由于2/(1+√5)=(√5-1)/2,可以先求出j=[a(√5-1)/2],若a=[j(1+√5)/2],那么a = aj,bj = aj + j,若不等于,那么a = aj+1,bj+1 = aj+1+ j + 1,若都不是,那么就不是奇异局势。然后再按照上述法则进行,一定会遇到奇异局势。<br><br><strong><span style="color:#993300; word-wrap:normal; word-break:normal">(三)尼姆博奕(Nimm Game):</span></strong>有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。<br><br><wbr><wbr><wbr>这种情况最有意思,它与二进制有密切关系,我们用(a,b,c)表示某种局势,首先(0,0,0)显然是奇异局势,无论谁面对奇异局势,都必然失败。第二种奇异局势是(0,n,n),只要与对手拿走一样多的物品,最后都将导致(0,0,0)。仔细分析一下,(1,2,3)也是奇异局势,无论对手如何拿,接下来都可以变为(0,n,n)的情形。<br><br><wbr><wbr><wbr>计算机算法里面有一种叫做按位模2加,也叫做异或的运算,我们用符号(+)表示这种运算。这种运算和一般加法不同的一点是1+1=0。先看(1,2,3)的按位模2加的结果:<br><br>
1 =二进制01<br>
2 =二进制10<br>
3 =二进制11 (+)<br>
———————<br>
0 =二进制00 (注意不进位)<br><br><wbr><wbr><wbr>对于奇异局势(0,n,n)也一样,结果也是0。<br><br><wbr><wbr><wbr>任何奇异局势(a,b,c)都有a(+)b(+)c =0。<br><br>
如果我们面对的是一个非奇异局势(a,b,c),要如何变为奇异局势呢?假设 a < b< c,我们只要将 c 变为 a(+)b,即可,因为有如下的运算结果: a(+)b(+)(a(+)b)=(a(+)a)(+)(b(+)b)=0(+)0=0。要将c 变为a(+)b,只要从 c中减去 c-(a(+)b)即可。</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
获胜情况对先取者进行讨论:
异或结果为0,先取者必败,无获胜方法。后取者获胜;
结果不为0,先取者有获胜的取法。
<wbr></wbr>拓展:任给N堆石子,两人轮流从任一堆中任取(每次只能取自一堆),取最后一颗石子的人获胜,问先取的人如何获胜?
根据上面所述,N个数异或即可。如果开始的时候T=0,那么先取者必败,如果开始的时候T>0,那么只要每次取出石子使得T=0,即先取者有获胜的方法。
<wbr></wbr>
<wbr><span style="color:#9C5A3C; word-wrap:normal; word-break:normal"><strong>【综合一、三给出】</strong></span></wbr>
任给N堆石子,两人轮流从任一堆中任取(每次只能取自一堆),规定每方每次最多取K颗,取最后一颗石子的一方获胜.问先取的人如何获胜?
与上面的问题比,这个更复杂一些,我们可以这样做
令Bi=Ai mod(K+1)
定义T‘=B1 xor B2 xor ... xor Bn
如果T‘=0 那么没有获胜可能,先取者必败
如果T’>0 那么必然存在取的方法,使得T‘=0,先取者有获胜的方法
假设对方取了在Ai中取了r<=K个
如果Ai中剩下的石子多于K 那么就在Ai中取走K+1-r个则Bi不变 T‘还是0
如果Ai<=K 那么我们需要重新计算Bi和T‘ 按照上面的方法来做就可以了
<wbr></wbr>
下面对wythoff博弈真的讲的超详细~~
【补】EP6: Wythoff’s Game (威佐夫博弈)
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://yjq24.blogbus.com/logs/42826226.html
大致上是这样的:有两堆石子,不妨先认为一堆有10,另一堆有15个,双方轮流取走一些石子,合法的取法有如下两种:
1)在一堆石子中取走任意多颗;
2)在两堆石子中取走相同多的任意颗;
约定取走最后一颗石子的人为赢家,求必败态(必胜策略)。
这个可以说是MR.Wythoff(Wythoff于1907年提出此游戏)一生全部的贡献吧,我在一篇日志里就说完有点残酷。这个问题好像被用作编程竞赛的题目,网上有很多把它Label为POJ1067,不过如果学编程的人不知道Beatty定理和Beatty序列,他们所做的只能是找规律而已。不熟悉的人可以先在这里玩几局~
简单分析一下,容易知道两堆石头地位是一样的,我们用余下的石子数(a,b)来表示状态,并画在平面直角坐标系上。
用之前的定理:有限个结点的无回路有向图有唯一的核<wbr><span style="word-wrap:normal; word-break:normal; font-family:新宋体">中所述的方法寻找必败态。先标出(0,0),然后划去所有(0,k),(k,0),(k,k)的格点;然后找y=x上方未被划去的格点,标出(1,2),然后划去(1,k),(k,2),(1+k,2+k),同时标出对称点(2,1),划去(2,k),(1,k),(2+k,1+k);然后在未被划去的点中在y=x上方再找出(3,5)。。。按照这样的方法做下去,如果只列出a<=b的必败态的话,前面的一些是(0,0),(1,2),(3,5),(4,7),(6,10),…</span></wbr>
接下来就是找规律的过程了,忽略(0,0),记第n组必败态为(a[n],b[n])
命题一:a[n+1]=前n组必败态中未出现过的最小正整数
[分析]:如果a[n+1]不是未出现的数中最小的,那么可以从a[n+1]的状态走到一个使a[n+1]更小的状态,和我们的寻找方法矛盾。
命题二:b[n]=a[n]+n
[分析]:归纳法:若前k个必败态分别为,下证:第k+1个必败态为
从该第k+1个必败态出发,一共可能走向三类状态,从左边堆拿走一些,从右边堆拿走一些,或者从两堆中拿走一些.下面证明这三类都是胜态.
情况一:由命题一,任意一个比a[k+1]小的数都在之前的必败态中出现过,一旦把左边堆拿少了,我们只要再拿成那个数相应的必败态即可。
情况二(从右边堆拿走不太多):这使得两堆之间的差变小了,比如拿成了,则可再拿成;
情况二(从右边堆拿走很多):使得右边一堆比左边一堆更少,这时类似于情况一,比如拿成了(其中a[m]
;
情况三:比如拿成,则可再拿成.
综上所述,任何从出发走向的状态都可以走回核中.故原命题成立.
以上两个命题对于确定(a[n],b[n])是完备的了,给定(0,0)然后按照这两个命题,就可以写出(1,2),(3,5),(4,7),…
这样我们得到了这个数列的递推式,以下我们把这两个命题当成是(a[n],b[n])的定义。
先证明两个性质:
性质一:核中的a[n],b[n]遍历所有正整数。
[分析]:由命题一,二可得a[n],b[n]是递增的,且由a[n]的定义显然。
性质二:A={a[n]:n=1,2,3,…},B={b[n]:n=1,2,3,…},则集合A,B不交。
[分析]:由核是内固集,显然。
看到这里大家有没有想到Beatty序列呢,实际上a[n]和b[n]就是一个Beatty序列。
,有,解方程
得,到此,我们找到了该必败态的通项公式。
实际上这组Beatty序列还有一些别的性质,比如当一个数是Fibonacci数的时候,另一个数也是Fibonacci数;而且两者的比值也越来越接近黄金比,这些性质在得到通项公式之后不难证明。
总的来说,这个问题给我们了哪些启示呢?首先用定理所说的方法找核,然后给出核的规律(递推,或是通项)并且证明。最后附上一张对应的必败态图.
分享到:
相关推荐
POJ 1006 源代码——中国剩余定理分析POJ 1006 源代码——中国剩余定理分析POJ 1006 源代码——中国剩余定理分析
The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has no public highways. So the traffic is difficult in Flatopia. The Flatopian government is aware of this problem....
poj 2488——dfs深度优先遍历 //给行数列数,求问能否遍历,给出字典序的一种遍历
POj 1001源代码——高精度乘单精度POj 1001源代码——高精度乘单精度POj 1001源代码——高精度乘单精度POj 1001源代码——高精度乘单精度
POJ 是“北京大学程序在线评测系统”(Peking University Online Judge)的缩写,是个提供编程题目的网站,兼容Pascal、C、C++、Java、Fortran、Python等多种语言。可以按照分类,在POJ上做题。
c表示有多少种珍珠 ai 表示第i种珍珠所需的数量 pi 表示第i种珍珠的价钱 每买一种珍珠都需要付额外的10 * pi的钱,便宜的珍珠可以用贵的珍珠来代替,求最少的钱的总数。
POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类
poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题报告poj 解题...
晒代码之二——多重背包(POJ1276)
poj 3752 字母旋转游戏.md
北京大学数据结构与算法课程作业代码,供广大学习c++的同学参考与学习
数据结构中的各算法,初级,中级,高级。如集合,图的规划,数据等
这题是道神题,神就神在,它既能让你搞懂网络流及其优化,还给了你很大的优化空间。
北京大学数据结构与算法课程作业代码,供广大学习c++的同学参考与学习
POJ第1861题源码 POJ第1861题源码 POJ第1861题源码
poj分类poj分类poj分类poj分类
北大POJ1159-Palindrome 解题报告+AC代码
poj 3414解题报告poj 3414解题报告poj 3414解题报告poj 3414解题报告
poj 1012解题报告poj 1012解题报告poj 1012解题报告poj 1012解题报告
poj 2329解题报告poj 2329解题报告poj 2329解题报告poj 2329解题报告