异或法求两个人取石子的必胜策略-应聘常考的笔试算法题

问题举例:

有三堆火柴,分别有3、5、7根火柴。有两个人,轮流从这三堆里面拿火柴。每次只能从一个堆里面拿,并且要求至少拿一根,最多拿当前堆的剩余的根数。
拿走最后一根火柴的人为失败者。

编程计算出先拿的人还是后拿的人肯定会胜利,具体拿的方案是什么?

 

不妨先思考一会……

 

 

 

解法:

任意N堆,假设有A1,A2,A3,A4....An个火柴
设T=A1 xor A2 xor ... xor An(所有的异或) Ti=T xor Ai(除i外所有的异或)
1.如果T=0 先取的人必然输
2.如果T>0 先取的人必然赢
他只要每次取的时候保持T=0就可以了
while(还有火柴)
{
a.在N堆中找第一个i,使得Ai>Ti(可以证明T>0时候必然存在这样的i)
b.然后从Ai中取走Ai-Ti个
c.那么T=Ti xor (Ai-(Ai-Ti))=Ti xor Ti=0
}

原理解析:

1. 首先给出下面会用到的几条异或的性质

性质1:异或满足交换律,结合律

性质2:如果a<2^t 那么有a xor 2^t=a+2^t,如果a的最高非零位为i,那么a xor 2^i =a-2^i

性质3:如果a<2^t b<2^t 那么(a xor b)+2^t=a xor (b+2^t)

证明:a<2^t b<2^t 则a xor b<2^

      由性质2有 (a xor b)+2^t=a xor b xor 2^t=a xor (b+2^t)

性质4:对任意a,偶数个a异或结果为0,奇数个a异或结果为a
--------------------------------------------------------------------------------

2.对一个非负整数序列定义平衡态和非平衡态

对n个非负整数序列A1,A2,...An

令T=A1 xor A2 xor ... xor An

    Ti=T xor Ai

定义平衡态为T=0 非平衡态为T>0
--------------------------------------------------------------------------------

3.证明必然存在从非平衡态到平衡态的转化

假设现在有T>0 我们证明必然存在t使得At>Tt

设A1 A2 ... An对应的二进制数中,最大数的最高非零位为i   并且设有m个数的最高非零位也是i

(1)当m为奇数

设At是其中的一个数,At>=2^i

那么剩下的数字有m-1个大于2^i的数字 因为m-1为偶数 所以这m-1个数字异或的值<2^i

其他n-m个小于2^i的数字异或的值<2^i

所以Tt=T xor At<2^i

所以At>Tt

 

(2)当m为偶数

不失一般性,假设A1 ... Am为这样的数字

T=A1 xor A2 xor ... xor Am xor ...xor An

=(A1 xor 2^i) xor (A2 xor 2^i) xor ... xor (Am xor 2^i) ... xor An

=B1 xor B2 xor ... xor Bm xor Am+1 xor ... xor An

其中Bt=At-2^i       t=1,2,...,m

如果序列B1 B2...An 满足(1)那么问题得解

否则继续做(2)的操作 直到满足(1)为止

我们选取此时序列为C1 xor C2 xor ... xor C? xor ... xor An

那么C1是A1与一系列的2^i异或后得到的

也就是说A1=C1+2^i1+2^i2+2^ix   i1>i2>...>ix

因为C1>T xor C1 所以T xor C1<2^ix

那么C1+2^i1+2^i2+...+2^ix>(T xor C1)+2^i1+2^i2+...+2^ix=T xor A1

则A1>T xor A1=Ti

 

现在我们只要从At中取走At-Tt就能保证T=0

T=Tt xor (At-(At-Tt))=Tt xor Tt=0

问题得证
--------------------------------------------------------------------------------

4.证明必然存在从平衡态到非平衡态的转化

对任意一个At 从中拿走任意x      0<x<At

因为T=Tt xor At=0 所以Tt=At

现在拿走x后 必然有Tt!=At

也就是T!=0

问题得证
--------------------------------------------------------------------------------

5.取石子问题

在上面的证明中,我已经证明了必然存在从平衡态到非平衡态的转化

下面我们看看这样的结论在经典的取石子问题中的应用

    ( 取 石 子 游 戏 1) 任给N堆石子,两人轮流从任一堆中任取(每次只能取自一堆),取最后一颗石子的人获胜,问先取的人如何获胜?

根据上面所述,如果开始的时候T=0,那么没有获胜的可能,如果开始的时候T>0,那么只要每次取出石子使得T=0即可

   ( 取 石 子 游 戏 2) 任给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‘ 按照上面的方法来做就可以了

posted on 2009-10-24 01:08  CLive Studio  阅读(1298)  评论(1编辑  收藏  举报

导航