0%

2026 杭电春季联赛 3——1002-汉诺塔(汉诺塔问题不要深究,其实就是三步)

题目大意

题目描述
你有三个栈 A,B,CA,B,C 和两个变量 L,RL,R(相当于两只手)。栈中元素必须时刻满足:越靠近栈底的元素越大。

初始时,L=R=0L=R=0AA 栈中有 nn 个元素(从栈底到栈顶依次为 n,n1,,1n, n-1, \dots, 1),B,CB, C 栈为空。目标是将所有元素移动到栈 CC,且操作过程中必须满足上述大小限制。

可以进行两种操作:

  • 操作 1(拿起):选择一个非空栈 SS 和一个值为 00 的变量 VVLLRR),弹出 SS 的栈顶元素,并将该元素的值赋给 VV

  • 操作 2(放下):选择一个值为 x0x \neq 0 的变量 VV 和一个栈 SS,将 xx 压入栈 SS,并将 VV 的值设为 00

求:将所有元素移到栈 CC 所需的最少操作 1(拿起)的次数
结果需要对 998244353998244353 取模。

输入格式
第一行输入一个整数 TT1T1001 \le T \le 100)表示测试数据组数。
接下来 TT 行,每行输入一个整数 nn1n1061 \le n \le 10^6)。

输出格式
输出 TT 行,每行一个整数,表示最少使用操作 1 的次数对 998244353998244353 取模的结果。

样例输入

1
2
3
4
5
6
5
1
2
3
10
100

样例输出

1
2
3
4
5
1
2
4
36
268435446

样例解释(对于 n=3n=3
初始状态: A(3,2,1),B(),C(),L=0,R=0A(3,2,1),B(),C(),L=0,R=0
操作 1: A(3,2),B(),C(),L=1,R=0A(3,2),B(),C(),L=1,R=0
操作 2: A(3,2),B(1),C(),L=0,R=0A(3,2),B(1),C(),L=0,R=0
操作 1: A(3),B(1),C(),L=2,R=0A(3),B(1),C(),L=2,R=0
操作 1: A(),B(1),C(),L=2,R=3A(),B(1),C(),L=2,R=3
操作 2: A(),B(1),C(3),L=2,R=0A(),B(1),C(3),L=2,R=0
操作 2: A(),B(1),C(3,2),L=0,R=0A(),B(1),C(3,2),L=0,R=0
操作 1: A(),B(),C(3,2),L=1,R=0A(),B(),C(3,2),L=1,R=0
操作 2: A(),B(),C(3,2,1),L=0,R=0A(),B(),C(3,2,1),L=0,R=0
共使用了 4 次操作 1,因此答案为 4。

思路讲解

PDF

直接打表是没什么思路的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1:1
2:2
3:4
4:6
5:9
6:13
7:17
8:22
9:28
10:36
11:44
12:54
13:66

再大,时间复杂度就要求太大了,没法继续打了。我们一般看规律是用差分与二阶差分这样子去看的,不过这个难度还是比较大,想把这个规律看出来,主要是

不过,汉诺塔问题嘛,就是 3 步

image

当然,由于我们现在有两只手,所以情况稍微复杂一点,就是我们在没有辅助杆的情况下我们可以移动的盘子就不一定是 1 个了

image

当然,具体是几根也不是那么重要了。可以使用 bfs 求解,或者你对自己的直觉和数学功底比较自信的话,也可以自己整一整。

1
2
3
4
5
6
7
8
9
没有辅助柱子的情况下,就靠两只手,所需要的拿去次数
_______________[ Sample Testcase #1 OUTPUT]_______________
1:1
2:2
3:5
4:10
5:2123213341(随便设置的哨兵值)
6:2123213341

其实套路和经典汉诺塔问题一样。

image

AC代码

AC
https://acm.hdu.edu.cn/contest/view-code?cid=1199&rid=18423

心路历程(WA,TLE,MLE……)

打表的时候遇到的问题

小心,不要把这个 step 也用于判重,如果 step 要用于优先队列,那么就使用两个比较器

初始化顺序问题,栈的初始化顺序有可能是反的