TSOJ 1559四柱汉诺塔
- 题目描述
“汉诺塔”,是一个众所周知的古老游戏。现在我们把问题稍微改变一下:如果一共有4根柱子,而不是3根,那么至少需要移动盘子多少次,才能把所有的盘子从第1根柱子移动到第4根柱子上呢? 为了编程方便,只需要输出这个结果除以10000的余数。
- 输入描述
该题含有多组测试数据,每组一个正整数n。(0< n ≤ 50000)
- 输出描述
一个正整数,表示把n个盘子从第1根柱子移动到第4根柱子需要的最少移动次数mod 10000的值。
- 样例输入
15
- 样例输出
129
- TIPS
四柱汉诺塔可以转化为三柱汉诺塔问题,将n个盘子由A柱移到D柱相当于将x(0 < x < n)个盘子先通过B,D柱移到C柱,再将n-x个盘子以三柱汉诺塔方式移到D柱,再将x个盘子通过A,B柱移到D柱。设n个盘子所需移动步数的函数为F(n),三阶汉诺塔中n个盘子的移动步数为hanoi(n) = 2n - 1。则
F(n) = min{ 2F(x) + hanoi(n-x) } (0 < x < n)
然而,由于题目中n的范围较大(n < 50000)不使用高精度只用以上的递归式是一定不行的,而同余定理又对min函数不成立。所以我们首先想到使用高精度,然后取获得答案的后4为即为answer
我们先用高精度写一遍不mod 10000的代码,如下
//四柱汉诺塔 高精度版
#include<bits/stdc++.h>
using namespace std;
//const int mod = 10000;
const string INF = "9000000000000000000000000000000000000";
void revstr(string &a){
for(int i = 0; i < (a.length()/2); i++){
char temp = a[i];
a[i] = a[a.length() - 1 - i];
a[a.length() - 1 - i] = temp;
}
}
string mini(string a, string b){
if(a.length() < b.length()) return a;
else if(a.length() > b.length()) return b;
else{
for(int i = 0; i < a.length(); i++){
if(a[i] > b[i]) return b;
else if(a[i] < b[i]) return a;
}
}
return a;
}
int <