题解 | #数楼梯#
数楼梯
https://www.nowcoder.com/practice/c7e5f164fa5d471f8f83c90fe4ee3f05
题目链接
题目描述
给定一段有 阶的楼梯,你每一步可以选择上
阶或者
阶。求从楼梯底端走到顶端共有多少种不同的走法。由于答案可能很大,请将结果对 998244353 取模后输出。
解题思路
这是一个经典的动态规划问题。
我们定义 为到达第
阶楼梯的不同走法数量。
要想到达第
阶楼梯,最后一步只可能是从第
阶或第
阶上来的:
- 从第
阶走
阶上来,这种情况的走法数量等于到达第
阶的走法数量,即
。
- 从第
阶走
阶上来,这种情况的走法数量等于到达第
阶的走法数量,即
。
因此,可以得到状态转移方程:
接下来确定初始状态(边界条件):
- 对于第
阶楼梯,只有一种走法(走
阶),所以
。
- 对于第
阶楼梯,有两种走法(“1阶+1阶” 或 “2阶”),所以
。
我们可以从 开始,根据状态转移方程依次计算出
的值。
在实现时,我们注意到计算 只需要
和
的值。因此,没有必要用一个数组来存储所有的
值,只需用两个变量滚动地记录前两项即可。这样可以将空间复杂度从
优化到
。
代码
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
if (n == 1) {
cout << 1 << "\n";
return 0;
}
if (n == 2) {
cout << 2 << "\n";
return 0;
}
// a 表示 dp[i-2],b 表示 dp[i-1]
long long a = 1, b = 2;
long long mod = 998244353;
for (int i = 3; i <= n; i++) {
long long c = (a + b) % mod;
a = b;
b = c;
}
cout << b << "\n";
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
if (n == 1) {
System.out.println(1);
return;
}
if (n == 2) {
System.out.println(2);
return;
}
// a 表示 dp[i-2],b 表示 dp[i-1]
long a = 1, b = 2;
long mod = 998244353;
for (int i = 3; i <= n; i++) {
long c = (a + b) % mod;
a = b;
b = c;
}
System.out.println(b);
}
}
n = int(input())
if n <= 2:
print(n)
else:
# a, b 分别表示 dp[i-2] 和 dp[i-1]
a, b = 1, 2
mod = 998244353
# 从第 3 阶开始计算
for i in range(3, n + 1):
# 滚动更新
a, b = b, (a + b) % mod
print(b)
算法及复杂度
- 算法:动态规划
- 时间复杂度:
,我们需要一个循环从
计算到
。
- 空间复杂度:
,我们只使用了常数个变量。