2018年1月月赛 打卡的汉诺塔 题解

2018年1月月赛 打卡的汉诺塔 题解

题目背景

比赛总是需要打卡题~~

题目描述

mh和cl最近玩起了汉诺塔。

相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘。

游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。

操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。现有n个盘子,有A、B、C三个柱子。

mh认为汉诺塔有最优解,而cl认为没有,这可怎么办呢?请你帮忙算算吧。

输入输出格式

输入格式

一行,包含一个正整数n,表示A柱子上有的盘子数量。

输出格式

一行,包含一个整数,表示最少需要的步数。

输入输出样例

输入样例#1:

1
2

输出样例#1:

1
3

说明

对于60%的数据,1<=n<=32。

对于100%的数据,1<=n<=64。

样例说明:

按A->B,A->C,B->C的方式即可三步完成。

通过手推n=1,2,3,4的情况,可以发现ans=pow(2,n)-1,故答案最大为2^64-1。

观察数据范围,发现n<=64。

因为int范围-2^31~2^31-1

long long范围-2^63~2^63-1

unsigned long long范围0~2^64-1

所以选用unsigned long long。

但又因为pow函数返回值为double类型,浮点数类型在数字很大时会发生浮点误差,因此用pow只能80分。故采用循环。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
unsigned long long ans=1,n;
cin>>n;
for(int i=1;i<=n;i++) ans*=2;
ans--;
cout<<ans;
return 0;
}

在上述代码中,我们发现,极端情况时ans=2^64,超过unsigned long long的0~2^64-1的范围,发生向上溢出(上溢),此时变为(2^64)-1-(2^64-1)=0。

之后又发生ans–,ans本该变为-1,但因为超过unsigned long long的0~2^64-1的范围,发生向下溢出(下溢),此时变为(-1)+1+(2^64-1)=2^64-1,即是答案。

--It's the end.Thanks for your read.--