其他分享
首页 > 其他分享> > P1255 数楼梯 题解

P1255 数楼梯 题解

作者:互联网

题目描述

楼梯有 \(N\) 阶,上楼可以一步上一阶,也可以一步上二阶。

编一个程序,计算共有多少种不同的走法。

输入格式

一个数字,楼梯数。

输出格式

输出走的方式总数。


解决

1. 递归的方法

有 \(1\) 阶楼梯时,输出 1 ;有 \(2\) 阶时,输出 2 ;否则,递归 pa(n-2)+pa(n-1)

这种方法十分好理解,但不能 AC 。

代码:

#include<bits/stdc++.h>
using namespace std;
int n;
long long pa(int n){
	if(n==1){
		return 1;
	}else if(n==2){
		return 2;
	}else{
		return pa(n-1)+pa(n-2);
	}
}
int main(){
	cin>>n;
	cout<<pa(n);
}

这种方法可以得到 \(50\) 分:

image-20220411181548551.png

上图中递推造成 TLE,是因为函数一遍又一遍地调用自身,耗费了大量时间。

那么有没有耗时较少的方法呢?我们不难想到递推。

2. 纯递推的方法

我们试着列举各种阶数和对应的走法数:

比如,在 \(N=1\) 时,只有一种走法:上 \(1\) 阶。

在 \(N=2\) 时,有两种走法:11 和 2 。

在 \(N=3\) 时,有三种走法:111、12 和 21 。

列举更多的数字,得到下表:

阶数 \(N\) 走法数
1 1
2 2
3 3
4 5
5 8
6 13
7 21

这个表格中的走法数神似斐波那契数列,只是第二项变成了 \(2\),由此写出:

由此得到代码:

#include<bits/stdc++.h>
using namespace std;
long long go[1010]={1,2};
int n;
int main(){
	cin>>n;
	for(int i=2;i<n;i++){
		go[i]=go[i-1]+go[i-2];
	}
	cout<<go[n-1];
	return 0;
} 

可是这种方法依然不能 AC:

image-20220411182640888.png

出现了两个 WA 和 RE,为什么?我们尝试输入本题的数据范围 \(5000\) ,输出了:

-8190626429588521950

这显然是得出的走法数超出了 long long 的范围。所以还得用高精度。

3. 递推+高精度的方法

利用高精度加法即可。

直接上代码:

#include<bits/stdc++.h>
using namespace std;
int n; // 楼梯阶数
int a[5002][5002]; // 能过即可,不要开太大

int l=1; // l 标记长度
int g_sum(int c){ // 负责高精度加法
	for(int i=1;i<=l;i++){ // 两数按位相加(这里必须用 <=1 ,否则 20 分)
		a[c][i]=a[c-1][i]+a[c-2][i];
	}
	for(int i=1;i<=l;i++){
		if(a[c][i]>9){ // 如果某一位上两位数
			a[c][i+1]+=a[c][i]/10; // 模拟进位
			a[c][i]=a[c][i]%10;
			
		}
		if(a[c][l+1]){ // 扩充容量
			l++;
		}
	}
}
int main(){
	a[1][1]=1; // 初始化 (等同于go[1]=1)
	a[2][1]=2; // 等同于go[2]=2
	cin>>n;
	for(int i=3;i<=n;i++){
		g_sum(i); // 相加即可
	}
	for(int i=l;i>0;i--){
		cout<<a[n][i]; // 倒着输出结果
	}
	return 0;
}

今天,你 AC 了吗?


附上做题过程(惨不忍睹):

image-20220411191701994.png

标签:P1255,走法,int,题解,long,pa,楼梯,递推
来源: https://www.cnblogs.com/liujimingblog/p/16131554.html