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

来源:互联网 发布:安云加速器for mac 编辑:程序博客网 时间:2024/05/22 13:07

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

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

Hanoi双塔问题
要点:首先要建立递推关系式
题目描述
给定A、B、C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的(下图为n=3的情形)。
题目图片
现要将这些圆盘移到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<iostream>using namespace std;#define SIZE 100001int 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<iostream>using namespace std;#define SIZE 100001int 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<<num[i];    }    cout<<endl;     num[1]-=1;    Record();    for(int i=len;i>=1;i--){        cout<<num[i];    }    cout<<endl;    return 0;    //COYG}

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

0 0
原创粉丝点击