斐波那契数列是一个经典的数学问题,它在计算机科学和数学中有着广泛的应用。斐波那契数列的每一个数字是前两个数字的和,通常形式为:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
1. 斐波那契数列的定义
斐波那契数列以递归的方式定义如下:
- F(0) = 0
- F(1) = 1
- F(n) = F(n-1) + F(n-2) 对于 ( n >= 2 )
2. 斐波那契数列的C/C++实现
2.1 递归实现
递归是实现斐波那契数列的一种直观方法,但这种方法效率较低,因为它会重复计算许多值。
#include <iostream>
int fibonacci(int n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
int main() {
int n = 10;
std::cout << "Fibonacci of " << n << " is " << fibonacci(n) << std::endl;
return 0;
}
2.2 动态规划实现
动态规划是解决斐波那契数列问题的一种更高效的方法。它通过存储已计算的值来避免重复计算。
#include <iostream>
#include <vector>
int fibonacci(int n) {
if (n <= 1) {
return n;
}
std::vector<int> dp(n + 1);
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= n; ++i) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
int main() {
int n = 10;
std::cout << "Fibonacci of " << n << " is " << fibonacci(n) << std::endl;
return 0;
}
2.3 空间优化的动态规划
可以进一步优化动态规划的实现,只存储最近的两个值。
#include <iostream>
int fibonacci(int n) {
if (n <= 1) {
return n;
}
int a = 0, b = 1, c;
for (int i = 2; i <= n; ++i) {
c = a + b;
a = b;
b = c;
}
return c;
}
int main() {
int n = 10;
std::cout << "Fibonacci of " << n << " is " << fibonacci(n) << std::endl;
return 0;
}
3. 性能比较
- 递归实现:时间复杂度为 O(2^n) ,空间复杂度为 O(n) 。
- 动态规划实现:时间复杂度为 O(n) ,空间复杂度为 O(n) 。
- 空间优化的动态规划:时间复杂度为 O(n) ,空间复杂度为 O(1) 。
4. 结论
在实际应用中,选择哪种实现方式取决于问题的具体需求。对于大数计算,空间优化的动态规划通常是最佳选择,因为它既高效又节省空间。递归方法虽然简单,但在处理大数时效率低下,不推荐使用。
希望这篇文章能帮助你理解如何在C/C++中实现斐波那契数列,并选择最适合你需求的方法。
题目例题
洛谷 P1011 [NOIP1998 提高组] 车站
题目描述
火车从始发站(称为第 1 站)开出,在始发站上车的人数为 a,然后到达第 2 站,在第 2 站有人上、下车,但上、下车的人数相同,因此在第 2 站开出时(即在到达第 3 站之前)车上的人数保持为 a 人。从第 3 站起(包括第 3 站)上、下车的人数有一定规律:上车的人数都是前两站上车人数之和,而下车人数等于上一站上车人数,一直到终点站的前一站(第 n−1 站),都满足此规律。现给出的条件是:共有 n 个车站,始发站上车的人数为 a,最后一站下车的人数是 m(全部下车)。试问 x 站开出时车上的人数是多少?
输入格式
输入只有一行四个整数,分别表示始发站上车人数 a,车站数 n,终点站下车人数 m 和所求的站点编号 x。
输出格式
输出一行一个整数表示答案:从 x 站开出时车上的人数。
解题思路:
注:题解为洛谷昵称为Hecarm7 的题解。
AC代码:
#include<iostream>
#include<cmath>
using namespace std;
typedef pair<int,int> PII;
int n,m,s,x;
PII a[25];
int main(){
cin>>s>>n>>m>>x;
a[1]={make_pair(0,1)};
a[2]={1,0};
a[3]={2,0};
for(int i=4;i<n;i++){
a[i].first=a[i-1].first+a[i-2].first-1;
a[i].second=a[i-1].second+a[i-2].second+1;
}
//cout<<a[n-1].first<<" "<<a[n-1].second<<endl;
int p=(m-a[n-1].first*s)/a[n-1].second;
cout<<a[x].first*s+a[x].second*p<<endl;
return 0;
}