高中OJ3033【NOIP2012模拟10.17】石子游戏

本文深入探讨了一种博弈论游戏的策略,通过分析不同参数K下游戏的必败状态,提出了有效的胜出策略。首先从最简单的情况出发,逐步推广到更复杂的场景,并给出具体的实现思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是一道坑比的博弈题。。。

尽管这道题实现起来很简单,但是思考的过程很有意义。


先从K=1的情况入手:

因为对方每次拿的数量都不能超过你上次拿的数量,所以可以得出必败结果都是2^i


思考:

可以把N转成二进制,例如N=25

则N(2)=11001


那么我们每次拿掉最末尾的一个1,则对方不能拿更高层的1。

拿完后N=24 (11000)


这样我们每一次都拿走最末尾的1,对方就只能拿0。

对方拿完后N=23 (10111)


而对方每次拿完0后又会产生新的1,一直到最后一个1被我们拿走。


必败情况就是2^i,例如:

N=32 (100000)

因为不能一次性拿完,那么我们只能拿走0,对方就可以每次拿走末尾的1。


K=2的情况:

必败结果为斐波那契数列。


思考:

因为斐波那契数列有一个性质:把任意一个数N分解成数列中的数相加,分解出的数两两都至少相差2倍以上(注意是以上)

所以我们只要把N分解成斐波那契数列,之后像K=1的情况一样计算。


其实K=1和K=2的情况的性质都是一样的。

因为K=1时分解的数列为2^i,即1 2 4 8 16 32 64……

K=2时斐波那契数列为1 2 3 5 8 13 21 34 55……


没看懂上两种情况请重新再看直到看懂为止↑↑↑↑

↑↑↑如果只想水30分的话就可以到此为止了↑↑↑↑↑↑


K>2的情况:

根据上面的两种情况,我们可以发现:

当K不同时,只是分解出的数列不同,计算其实是一样的。

那么我们只要计算出一个序列,用这个序列的数相加来表示N,并且每两个数都要相差K倍以上。


思考:

假设K=3,N=35。

先计算N=1

因为序列为空,所以第一项是1。


N=2

因为序列中只有1,所以第二项是2。


如此类推,第三项是3。


N=4

尽管1+3=4,但是因为1*3≥3,所以无法构成合法的序列,第四项为4。


如此类推,该序列为1 2 3 4 6 8 11 15……

而1+4+15=20,所以下一项是21。

补充:如果当前序列最大能构成N,即能构成1~N中任意一个数。


又如此类推,该序列为1 2 3 4 6 8 11 15 21 29 40……

最后一项已经比N大了,可以不用继续往下算了。


因为40≠35,所以可以获胜。

之后把N一直往下减,减到N=当前项。

答案就是当前位置对应的数,即7。


但是考虑到时间的问题,如果该序列有多项就要一个一个去减,时间就可能会爆。

设当前K计算出的序列为A,则用B[i]表示从1~i序列中能构成的最大数。

显然A[i]=B[i-1]+1,A[1]=1且B[1]=1。

之后计算B[i],找到一个最大的j,且A[j]*k<A[i]

因为当前的B[i]等于最大和当前项的倍数不超过K的数所能构成的最大数,再加上当前数,

所以B[i]=B[j]+A[i]。


最后补充:

假设当前所构成的序列为A,把A再加上一个数所能构成的最大数肯定比原来的序列A构成的数大,

所以枚举J这一步是线性的。


这道题想了我挺久的,把题解反复看了之后才想出来的。

总之,解决此类问题有3步:

①从最简单的方案入手研究。

②把范围扩大,推出公式。

③实现程序并优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值