【数论】[NOIP2007]Hanoi双塔问题

前几天Z老师给我们把历年noip普及组的数论题都找了出来 说真的 目前对于高精度还一窍不通的我 有些题真心不会 但是最后看看代码才发现 我基本上都没用到高精..
例如这个题 正解确实要用高精 但是我还是没有..我的做法已经在洛谷OJ发布了题解

题目
Hanoi双塔问题【Noip普及组】2007T4 [难度]普及组题目不评级 [标签]<高精><递推><递归><数论数学> (洛谷搜索P1096 1s128MB)

Hanoi双塔问题
要点:首先要建立递推关系式
题目描述
给定A、B、C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的(下图为n=3的情形)。
【数论】[NOIP2007]Hanoi双塔问题_第1张图片
现要将这些圆盘移到C柱上,在移动过程中可放在B柱上暂存。要求:
(1)每次只能移动一个圆盘;
(2)A、B、C三根细柱上的圆盘都要保持上小下大的顺序;
任务:设An为2n个圆盘完成上述任务所需的最少移动次数,对于输入的n,输出An。
输入输出格式
输入格式:
输入文件hanoi.in为一个正整数n,表示在A柱上放有2n个圆盘。
输出格式:
输出文件hanoi.out仅一行,包含一个正整数, 为完成上述任务所需的最少移动次数An。
输入输出样例
输入样例:① 1 ②2
输出样例:① 2 ②6
说明
【限制】
对于50%的数据,1<=n<=25
对于100%的数据,1<=n<=200 //这么小 暴力就是了[滑稽

我们可以用一个num[]数组来存储答案且num[1]代表个位 往后类推

#include
using namespace std;
#define SIZE 100001
int num[SIZE];
int n,len=1;
//COYG

n是我们要输入的数字 len代表输出答案的长度 首先要初始化
num[1]=1;
一定要注意 不要把num[1]初始为2 往后看你就会明白
然后就是记录移动
for(int i=1;i<=n;i++){Record();}
这里我们需要弄一个函数record来记录

void Record()
{
    int carry_bit=0;//我们应当考虑到进位的情况 所以建立一个变量记录进位 下面有用法
    for(int i=1;i<=len;i++){
        num[i]=num[i]*2;//双塔
        num[i]+=carry_bit;//如果有前一位进上来的数肯定要加上
        if(num[i]<10){
            carry_bit=0;//小于10肯定不会进位
        }
        else{//大于10有进位
            carry_bit=num[i]/10;//计算进上去的数
            num[i]=num[i]%10;//这一位%10储存 很好理解
            if(i==len){
                len=i+1;//之前说过len的意义 如果i已经和目前的len相等可是又进了一位 就必须要增加长度
            }
        }
    }
}
//COYG

调用了n次之后 我们好像已经计算出了n个塔移动的次数 但是如果我们此时输入 3 输出的答案应该是7 可却是8
原因是之前我们个位多加了一次 于是
num[1]-=1;
然后再执行一遍record获得2n的数量
最后倒叙输出

全代码如下

#include
using namespace std;
#define SIZE 100001
int num[SIZE];
int n,len=1;
void Record()
{
    int carry_bit=0;
    for(int i=1;i<=len;i++){
        num[i]=num[i]*2;
        num[i]+=carry_bit;
        if(num[i]<10){
            carry_bit=0;
        }
        else{
            carry_bit=num[i]/10;
            num[i]=num[i]%10;
            if(i==len){
                len=i+1;
            }
        }
    }
}
int main()
{ 
    cin>>n;
    num[1]=1;
    for(int i=1;i<=n;i++){
        Record();
    }
    for(int i=len;i>=1;i--){
        cout<cout<1]-=1;
    Record();
    for(int i=len;i>=1;i--){
        cout<cout<return 0;
    //COYG
}

差不多就这样 当然普及组的题很简单 如果是提高组的数论那么就要…
好好看书学数学!
一起共勉

转载于:https://www.cnblogs.com/ars4me/p/7536210.html

你可能感兴趣的:(【数论】[NOIP2007]Hanoi双塔问题)