0366 取石头三
* * * *
拉格朗日计划
* * * *
取石头三

有一堆共计n枚的石头,两名玩家轮流从此中取石,每次至少取一枚。

先手玩家可以从中取走任意枚石子,但不能全部取走。

此后的每轮中玩家可从堆中取走的石子数量的上限是其对手在上一轮所取走的石子数量的两倍。

取走最后一枚石子的玩家获胜。

例如,$n=5$时,张三先手,李四后手。

若张三取走多于一枚石子,则李四总能取走剩下的全部石子。

而若张三先取走一枚石子,则李四下一轮最多可取2枚石头。

若李四取走两枚石头,则第三轮张三也取走两枚并获胜。

若李四也取走一枚石子,则留下三枚石子。第三轮张三最多只能取走两枚石头,此时不论他如何选择,第四轮李四都能取走所有石头。

因此当$n=5$且双方都使用最优策略时先手玩家必败。

类似地$n=17$时,第一轮先手玩家取走1枚或4枚石头时都能必胜。

定义函数$M(n)$,若先手玩家必败,则$M(n)=0$,否则令$M(n)$为其第一轮最多能取走的石头数。

可以验证$\sum_{n=1}^{100}M(n)=728$。

求$\sum_{n=1}^{10^{18}}M(n)$的最后八位数字。

本题难度:



解答

计算一些$M(n)$并观察其分布可以发现其由一系列连续的整数片段组成。

记$a_n$为初值是$a_0=a_1=1$的斐波那契数列,则可以不完全归纳出: $$M(a_i+t)=\begin{cases}t & 0\le t\le\lfloor\frac{a_i-1}{2}\rfloor, \\ M(t) & \lfloor\frac{a_i-1}{2}\rfloor < t < a_{i-1}.\end{cases}$$ 从而可得 $$S(a_{i+1}-1)-S(a_i-1)=\frac{m_i(m_i+1)}{2}+S(a_{i-1}-1)-S(m_i),$$ 其中 $$m_i=\lfloor\frac{a_i-1}{2}\rfloor.$$ 直接计算即得结果$88351299$。

注:因使用cache装饰器作记忆化搜索,以下代码为Python 3。

from functools import *

@cache
def S(n):
    if n<4:return 0
    s,a,b,c=0,1,1,2
    while b<=n:
        s+=m*(m+1)//2+S(a-1)-S(m) if (m:=(b-1)>>1)<=n-b else (n-b)*(n-b+1)//2
        a,b,c=b,c,b+c
    return s

print(S(10**18)%(10**8))