传送门:牛客
给定A、B、C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的(下图为n=3的情形)。现要将这些圆盘移到C柱上,在移动过程中可放在B柱上暂存。要求:
(1)每次只能移动一个圆盘;
(2)A、B、C三根细柱上的圆盘都要保持上小下大的顺序;
任务:设An为2n个圆盘完成上述任务所需的最少移动次数,对于输入的n,输出An。
输入:
1
输出:
2
关于汉诺塔问题,在这里有详细的介绍和代码解释,如果对汉诺塔问题的递推关系不清楚的话可以跳转观看后继续
然后我们看向这道题,运用基本汉诺塔问题的思想去看这道题,你会发现只要将每次的移动都重复一遍即可,我们就得到了这样一个式子f(n)=2*(2^n-1)
,但是作为当年普及组的最后一题显然不能是这么简单的,这道题的n达到了200,而之前我们的普通汉诺塔才26,所以我们就需要采用高精度的方法了,这里也不难,只要不断乘2即可
如果高精度不会请看向这里
下面为了实现方便,将直接计算2^(n+1)-2
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <stack>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
ll x=0,w=1;char ch=getchar();
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x*w;
}
#define maxn 1000000
int ans[30000];
int main() {
int n;
n=read();
ans[1]=2;int lens=1;
for(int i=2;i<=n+1;i++) {
int jw=0;
//高精度乘2部分
for(int j=1;j<=lens;j++) {
ans[j]=ans[j]*2+jw;
jw=ans[j]/10;
ans[j]%=10;
}
if(jw!=0) {
lens++;
ans[lens]+=jw;
}
}
//因为后面需要减2,可能会涉及到补位的问题
int pos=1;
while(ans[pos]<2) {
pos++;
}
//pos!=1表示该位就可以直接减掉2,不需要前面的退位
if(pos!=1) {
lens--;
ans[pos]--;
int ppos=pos-1;
for(int j=ppos;j>=2;j--) ans[ppos]=9;
ans[1]=ans[1]+10-2;
for(int i=lens;i>=1;i--) cout<<ans[i];
}else {
ans[pos]-=2;
for(int i=lens;i>=1;i--) cout<<ans[i];
}
return 0;
}