NOIP题目解析之取石子问题

Posted 明立

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP题目解析之取石子问题相关的知识,希望对你有一定的参考价值。

题目:
现有5堆石子,石子数依次为3,5,7,19,50.甲乙两人轮流从任一堆中取石子,取最后一颗石子的一方获胜,甲先取,请问甲有没有获胜策略?如果有,甲第一步应在哪一堆里取多少?

解析:
在解这一道题之前,我们可以先来把问题简化。把五堆石子转化成两堆,石子数分别为 3 和 5 。探查其规律,我们发现,要使甲获胜,必须使得存在一种可能,就是当甲取了石子之后,到乙开始取石子时,两堆石子的数目要保持一致。这样,不管乙取多少,只要甲在另一堆取走相同的数量的石子,则甲最后必定是最后一个取走最后一颗石子的。(可以在纸上进行一下推算)

那么,在这个简化的题目上,我们发现很重要两个判定:
1)要想甲取胜,则当其取石子时,两堆石子必定是保持不平衡的状态,此时甲取走多余的部分,使得两堆石子保持平衡
2)当乙在两堆数目相同的石子上任意选一堆取一定的棋子时,都必定会使得当前两堆棋子形成一种不平衡的状态(两端数据不对称即为不平衡)

而我们发现,要使得甲获胜,则必须保证在其取石子前,石子的数据应该是保持不平衡的状态,我们姑且用非负态来表示这种不平衡的状态。反之,我们则用负态来表示平衡的状态。那么前面根据两个判定,我们可以得出另外一个结论:

要使得非负态转化成负态,只有一种操作,就是保持平衡。而当我们处于负态时,可以通过操作一定的石子改变这种状态

也就是说,其实我们可以捡走石子的过程,就是不断在改变这两种状态的过程。而只要甲能够保持在这个状态转换的过程中,一直处于将非负态转化成负态的过程即可获胜。

那么,我们明白了甲要获胜的一个原理,就要继续回到我们的实践操作之——应该取走多少石子。

因为我们发现,整一个过程就是两种状态的切换,也就是可以和不可以的问题。那当我们面临着两种情况的分析的时候,我们一般使用符合计算机思维的二进制数字进行分析,那什么是二进制呢?这个时候就需要先普及一个知识点:
基础:二进制
二进制数字,指的是逢二进一,意思是当我们从0开始数数时,当数到2时,需要向前进一位,而当前位为0。也就是说,二进制数字只有0 和 1这两个数字。它和十进制的区别就在于什么时候进位。我们来看一组二进制和10进制的对比:

二进制                            10进制
0                                   0
1                                   1
10                                  2
11                                  3
100                                 4
101                                 5
110                                 6
111                                 7
1000                                8
1001                                9
1010                                10

我们发现,同样是数字,在二进制里面就没有出现过2以上的数字,这也是因为我们逢二进一的结果。
那我们说到要用二进制,可是题目的数据又是十进制的,那我们怎么实现二进制和10进制的转换呢?我们来看一下:

二进制和十进制的相互转换
1.十进制转化成二进制:
当我们要将10进制转化为2进制时,有一个比较简单的方法,我们可以通过筛查的方式实现,什么意思呢?跟着思路走:
1.在纸上画出一个筛选的“柱子”,从右到左分别是2的0次方—–2的n-1次方。比如:

  256  128   64    32   16   8  4  2  1

然后,把我们要转换的10进制数取出来(以数字9为例),我们判断这个数字在哪个区间段之间(9在 8->16之间),取最小值(8)。,在8的上面写1。也就是

                             1 
  256  128   64    32   16   8  4  2  1

接着,用9减去8,剩余的数字是1,重复上述的操作,直到10进制数最终减为0(在这里,1对应1,在1上面写下1,此时1-1已经等于0),而柱子表示为:

                             1        1
  256  128   64    32   16   8  4  2  1

最后:把所有没有1的部分写上0,即

   0    0    0      0    0    1  0  0  1
  256  128   64    32   16    8  4  2  1

最左边一个1往左的所有0可以删去,即最后的结果为:1001
2.二进制转10进制
我们上面介绍了10进制转2进制的方式,那二进制转10进制呢,其实也是通过我们的“柱子”。怎么来呢?
第一步,把柱子写出来:

256 128 64 32 16 8 4 2 1

第二步:把二进制数字的最右边和柱子的最右边契合,以10010为例:

               1 0 0 1 0
256 128 64 32 16 8 4 2 1

第三步:把二进制中1所在的柱子的数字拿出来,相加,就是

16+2=18

18就是我们想要的结果~

好啦,说完了二进制,我们继续回归刚才的问题,我们同样以3 和 5 为例,我们要判断当前棋子的分布式哪一种状态,是不是就是看这两堆石子是不是处于平衡的状态。比如:

3的二进制是:          011
 则其对应状态应该也是   011 
 而5的二进制是:       101 
 则我们可以很清晰地看到,应该对应的状态
 除于非负态,甲有获胜策略。那要取多少石子呢?
 是不是就是 101 - 011=5-3=2.

上面的是以两堆石子为例的情况分析。那当我们面临多堆石子的情况时,应该怎么确定应该对应的状态呢?其实我们可以发现,只要我们保证在二进制情况下,每一次甲取完之后,只要各个数位的1的总和为偶数,则不论乙怎么取其中的哪一堆上的数字,甲都能通过取走其他堆的石子,使其继续保持偶数的状态。比如:

0 1 1
0 1 1

0 2 2
 我们发现往上往下看,每个
 数位上的1都是偶数个(0也算偶数)

那么,对于 3 5 7 19 50这5堆石子来说,因为50的数目是最大的,也就是我们有且仅有取这一堆石子的时候,才能保证把剩余的不平衡的状态去掉,变成一个平衡的状态,也就是非负态。所以,我们题目可以理解为:
当目前有3 5 7 19这四堆石子时,添加多少石子可以使其变成负态。即:

数字                                   对应的二进制数
3                                         00011
5                                         00101
7                                         00111
19                                        10011 

个数位的1的个数:                           10234
那我们的对应状态
就应该是(奇数为1,偶数为0):               10010                                

也就是说,要使得当前状态为负态,则第五堆的石子数量应该是(10010),转化成10进制数,就是18。
也就是说,当甲第一次在50个石子里面取(50-18=32)个石子时,能够使得当前的状态为负态。也就是必胜的策略。解题完毕~~~

以上是关于NOIP题目解析之取石子问题的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 Roy&October之取石子

P4018 Roy&October之取石子

ACM-尼姆博弈之取(m堆)石子游戏——hdu2176

Roy&October之取石子

Roy&October之取石子II

子集背包再进化--石子对撞问题