专栏文章
题解:P1962 斐波那契数列
P1962题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mip6fzms
- 此快照首次捕获于
- 2025/12/03 06:56 3 个月前
- 此快照最后确认于
- 2025/12/03 06:56 3 个月前
前言
此题解给不会矩阵和想有易懂数学证明方法的人。
题目简述
求斐波拉契数列第 项。
题目思路
首先根据斐波拉契数列的递推式:,很容易想到一个暴力代码,如下:
CPPint n, a = 1, b = 1;
cin >> n;
for (int i = 3; i <= n; i ++ ) {
int t = a;
a = a + b;
b = t;
}
cout << a << '\n';
时间复杂度 显然会
TLE。于是我们就要优化递推式。结论:。
证明:
考虑一个数列 ,其第 项表示有 级台阶(每步只能上 级或 级)的方案数。显然 。第 级台阶只能从第 级或第 走来。根据加法原理可得 。对比斐波拉契递推式可得 。考虑现在有 给台阶则走到最高的台阶的方案可以分成两类:
- 先走上第 级台阶(方案数为 )再走上第 级台阶(方案数为 ),根据乘法原理可得此类方案数为 。
- 先走上第 级台阶(方案数为 )再直接走上第 级台阶(方案数为 ),最后走上第 级台阶(方案数为 ),根据乘法原理可得此类方案数为 。 根据加法原理可得 即 。
现在我们要计算 我们可以考虑把 拆分成 和 。根据公式,。这样我们就可以递归求解,记忆化优化时间复杂度 。
AC code
CPP#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 1e9 + 7;
int n;
unordered_map<int, int> fie = {{1, 1}, {2, 1}};
int f(int x) {
if (fie[x] != 0) return fie[x];
int m = x >> 1;
return fie[x] = (f(m + 1) * f(x - m) % mod + f(m) * f(x - m - 1) % mod) % mod;
}
signed main(){
ios::sync_with_stdio(false); cin.tie(nullptr);
cin >> n;
cout << f(n) << '\n';
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...