刷题Day13高精度斐波那契数列

前言

 这题是昨天晚上快到12点的时候AC的,因此没来得及写题解,今天中午补一下题解。
 先放题目链接:P1255 数楼梯
在这里插入图片描述
解题思路:
 这题其实还是蛮简单的,记 f [ N ] f[N] f[N]为台阶数为N的时候有的走法数量。先来看三个特殊情况,(1)当N=0的时候,没有台阶也就不存在走的方式(这里会被输入数据卡一下),因此 f [ 0 ] = 0 f[0]=0 f[0]=0 (2)当N=1的时候,就一种上楼方法,一步到位,因此 f [ 1 ] = 1 f[1]=1 f[1]=1(3)当N=2的时候,如果先登一步,再登一步,是一种,第二种是一次登两步,所以这时候是2,即 f [ 2 ] = 2 f[2]=2 f[2]=2。接着往下再看,当N>2的时候,我想要登上去,有两种情况,一种是处于N-1阶台阶处走一步,登顶;另一种是处于N-2阶台阶处直接走两步,登顶,那么归纳起来就是 f [ N ] = f [ N − 1 ] + f [ N − 2 ] f[N]=f[N-1]+f[N-2] f[N]=f[N1]+f[N2]。这里,N=2情况不符合,那就分开讨论,在计算 f [ 1 ] − f [ N ] f[1]-f[N] f[1]f[N]时假设它为1,当输入数据N=0直接输出0。但是在这里我们可以看到, f [ N ] f[N] f[N]的本质就是斐波那契数列。
 递推关系式确定了,剩下的一个问题就是模拟高精度。因为输入数据中N最大为5000,而 f [ 5000 ] f[5000] f[5000]实际上是个很大的数字(试了下,大概是1000位数)所以必须去模拟这样的精度。我的方法是开一个2000多长度的char数组,然后数组从低位到高位依次从0开始存放,加的时候也是对应位相加,然后考虑进位一直加到最高位。
 按照上述做法,还需要考虑空间复杂度的为题,假设每一个number对应一个上述那么大的char数组,而实际上N很小的时候有很多空间会被浪费,实际上如果真的是每一个number对应一个char数组,很容易造成内存空间的爆炸,再来看表达式,发现实际上三个char数组就能解决这个递推关系了,因此可以把空间复杂度很好的控制下来。
 最后给出我的AC代码:

#include <stdio.h>
#include <stdlib.h>
struct node{
	char a[2000];
};


int main(int argc, char *argv[]){
    int N,i,j;
    scanf("%d",&N);
    if(N>0){
    struct node number[3];
    for(i=0;i<=2;i++){
    	if(i==0||i==1){
    		for(j=0;j<1999;j++){
    			if(j==0)
    			 number[i].a[j]='1';
    			else
    			 number[i].a[j]='0';
			}
    		number[i].a[1999]='\0';
		}else{
			for(j=0;j<1999;j++)
			 number[i].a[j]='0';
			number[i].a[1999]='\0';
		}
	}
	int add=0,order1=0,order2=1,order3=2;
    for(i=2;i<=N;i++){
    	add=0;
    	for(j=0;j<1999;j++){
    		if((number[order1].a[j]+number[order2].a[j]-48+add)>=':'){
    			number[order3].a[j]=number[order1].a[j]+number[order2].a[j]-48+add-10;
    			add=1;
			}else{
				number[order3].a[j]=number[order1].a[j]+number[order2].a[j]-48+add;
				add=0;
			}
		}
		order1++;
		if(order1>2)
		 order1=0;
		order2++;
		if(order2>2)
		 order2=0;
		order3++;
		if(order3>2)
		 order3=0;
	}
    for(i=1998;i>=0;i--){
    	if(number[order2].a[i]=='0')
    	  ;
    	else
    	  break;
	}
	while(i>=0){
		printf("%c",number[order2].a[i]);
		i--;
	}
}else{
	printf("0");
}
	return 0;


}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值