首页 > 其他分享 >【PE806】Nim on Towers of Hanoi(汉诺塔游戏,生成函数)

【PE806】Nim on Towers of Hanoi(汉诺塔游戏,生成函数)

时间:2022-10-29 11:36:06浏览次数:52  
标签:柱子 Nim Towers 第三根 步数 汉诺塔 盘子 oplus

PE:Project Euler

题意:

汉诺塔游戏是如下的问题:有三根柱子,第一根柱子套有 \(n\) 个圆盘,圆盘从上往下半径递增。每次操作可以把套在某根柱子上的最上面的那个圆盘移到另一个柱子上。但需保证过程中每根柱子都始终满足大盘在下小盘在上。现要在最小的步数内,将这 \(n\) 个圆盘仍按从上往下半径递增的顺序,全部套在第三根柱子上。

现在按最优策略进行汉诺塔游戏。过程中,设 \(a,b,c\) 是当前三根柱子上的盘子个数,若 \(a\oplus b\oplus c=0\),那么让答案加等于当前的步数。求最后答案。

\(n=10^5\)。

题解:

首先得知道汉诺塔游戏的最优策略是啥。设 \(n\) 个盘子的答案为 \(f_n\)。

考虑最大的那个盘子,即第 \(n\) 个盘子。显然存在一个时刻把它移到第三根柱子并固定下来永远不动。那么此时需要满足:第一根柱子只有第 \(n\) 个盘子、第二根柱子按半径递增套着剩下 \(n-1\) 个盘子、第三根柱子为空。

那么我们需要把原来第一根柱子上的 \(n-1\) 个盘子全部移到第二根柱子,这个过程的步数下界是 \(f_{n-1}\)(显然第一根柱子上的第 \(n\) 个盘子并不会使得步数在 \(f_{n-1}\) 的基础上变得更少),而显然这个步数下界是可以达到的(忽略第 \(n\) 个盘子即可,因为它是全局最大的)。

同理可以证明,最优方案是用 \(f_{n-1}\) 步把第二根柱子上的 \(n-1\) 个盘子移到第三根柱子上。

从而得到 \(f_n=2f_{n-1}+1=2^n-1\),以及最优策略(显然最优策略唯一,我们不可能在动 \(n-1\) 个盘子的时候动第 \(n\) 个盘子,这样会使答案变劣)。

现在转到另一个问题:我们先考虑满足 \(a+b+c=n\) 且 \(a\oplus b\oplus c=0\) 的 \((a,b,c)\) 应满足什么条件。

可以归纳证明,在 \(a\oplus b\oplus c=0\) 的前提下,\(a+b+c=n\) 过程中每次进位不超过 \(1\)。同时,可以根据 \(a+b+c\) 在某位上的值确定上一位具体往这一位进的是 \(0\) 还是 \(1\)。同时,若上一位进了 \(0\),那么上一位必定是三个 \(0\);若上一位进了 \(1\),那么上一位 \(a,b,c\) 中必是两个 \(1\) 一个 \(0\)。

那么可以在 \(O(3^{\operatorname{popc}(n)})\) 的时间复杂度内枚举每一种 \((a,b,c)\)。

又注意到若 \((a,b,c)\) 在第 \(x\) 步出现了,那么对称地有 \((c,b,a)\) 在第 \(2^{n}-1-x\) 步出现。

于是,只需对于某个 \((a,b,c)\),知道它在过程中出现了多少次即可。

考虑 DP,设 \(f_{a,b,c}\) 表示在 \(n=a+b+c\) 的汉诺塔游戏中,\((a,b,c)\) 在过程中出现的次数。于是 \(f_{a,b,c}=f_{c,b,a}\)。

考虑 \((a,b,c)\) 出现时,第 \(n\) 个盘子的位置,若它在第一根柱子上,那么方案数为 \(f_{a-1,c,b}\);若它在第三根柱子上,那么方案数为 \(f_{b,a,c-1}\)。从而 \(f_{a,b,c}=f_{a-1,c,b}+f_{b,a,c-1}\)。

设 \(f\) 对应的生成函数为 \(F(x,y,z)\)。那么上式意味着 \(F(x,y,z)=xF(x,z,y)+zF(y,x,z)+1\),加一是因为 \(f_{0,0,0}=1\)。

这个生成函数和一般的生成函数不太一样,因为它涉及到下标的位置交换,即维度与维度之间的交换。那么仅靠这一条方程是不够的,我们要把其他对称的方程都写出来。

令 \(F_x=F(y,x,z)=F(z,x,y)\),\(F_y=F(x,y,z)=F(z,y,x)\),\(F_z=F(x,z,y)=F(y,z,x)\)。类似地我们可以得出三条等式:

\[F_y=xF_z+zF_x+1\\ F_x=yF_z+zF_y+1\\ F_z=xF_y+yF_x+1 \]

解得 \(F(x,y,z)=F_y=\dfrac{(1+y)(1+x-y+z)}{1-x^2-y^2-z^2-2xyz}=(1+y)(1+x-y+z)\sum\limits_{i=0}^{\infty}(x^2+y^2+z^2+2xyz)^i\)。

把 \((1+y)(1+x-y+z)\) 展开,再枚举 \(i\),要算的就是 \([x^ay^bz^c](x^2+y^2+z^2+2xyz)^i\)。这个东西可以 \(O(1)\) 算:考虑 \(2xyz\) 这一项在乘积中的幂次 \(k\),那么需要满足 \(3k+2(i-k)=a+b+c\),容易解出 \(k\),然后容易解出 \(x^2,y^2,z^2\) 分别在乘积中的幂次,然后用组合数一算就好了。

时间复杂度 \(O(3^{\operatorname{popc}(n)}\times n)\)。

标签:柱子,Nim,Towers,第三根,步数,汉诺塔,盘子,oplus
From: https://www.cnblogs.com/ez-lcw/p/16838354.html

相关文章

  • unity 使用动画器覆盖控制器(AnimatorOverrideController)快速创建新对象的动画控制器
    注释:假设你已经创建好了一个怪物对象的基础动画控制,此时需要在添加一个全新的敌人,你又懒得从新写一堆参数和代码,那么就可以使用这种重写控制器来快速生成控制器参数则使......
  • Leetcode第907题:子数组的最小值之和(Sum of subarrays minimums )
    解题思路既然我们不能先遍历区间,然后找最小值,那么我们不如顺序倒过来,对于每个值,我们找有多少区间里面,它是最小值。对于一个数字A[i]来说,如果在某个区间[j,k]里面它......
  • 17.CF739C Alyona and towers 区间合并线段树
    17.CF739CAlyonaandtowers区间合并线段树给定序列,要求支持区间加,以及查询最长先增后减子区间(单峰序列)长度非常典型的区间合并线段树,记录左右起LIS,LCS,单峰洛谷传送门:......
  • Adobe Animate(An)2023软件安装包下载及安装教程
    AdobeAnimate(An)2023软件简介:AdobeAnimate2023是Adobe推出的一款功能强大的动画制作软件,能够设计适合游戏、应用程序和Web的交互式矢量动画和位图动画。让卡通和横幅广告......
  • LeetCode_Array_64. Minimum Path Sum (C++)
    目录​​1,题目描述​​​​2,思路​​​​3,代码【C++】​​​​4,测试效果​​1,题目描述Givenamxngridfilledwithnon-negativenumbers,findapathfromtopleftt......
  • LC 907 Sum of Subarray Minimums
    DecrisptionGivenanarrayofintegersarr,findthesumofmin(b),wherebrangesoverevery(contiguous)subarrayofarr.Sincetheanswermaybelarge,retu......
  • HDU 1394 Minimum Inversion Number
    题目链接:​​传送门​​求出原数组的逆序对算把一个数从对头拿到队尾的过程中产生的贡献诶我好像昨天做过这个题#include<iostream>#include<cstdio>#include<cstring......
  • manim 3.0优化
    我们考察能不能用简洁的形式完成mobject的预定义1、赋值executenarrator/mobjects/others2、预处理总的来说,即为函数处理,包括shift、next_to、opacityscale等其中......
  • unity editor 读取FBX下的animtion clip文件
    使用ModelImporter可以读取FBX下数据:1ModelImportermodelImporter=(ModelImporter)AssetImporter.GetAtPath(modelAssetPath);2......
  • manim 3.0
    随着视频的深入,暴露的问题越来越多,其中主要的问题是自定义函数的混乱,我的解决方法是构造自己的完备的函数库manim的主结构是mobject和animation,我想我的函数库大致也要这......