斐波拉西数列一般最简单想到的就是递归来解决,暴力递归法时间复杂度为O(2^n),这种时间复杂度在项数n比较大的时候就计算不了了,反而直接使用循环时间复杂度为O(n)。但是还有一个问题,斐波拉西数列高次项十分大,比如第一百项的大小为218922995834555169026(设第一项为0)。这么大的数计算机变量无法直接存储,使用科学计数法也会因为精度问题导致不够准确。所以需要解决的问题是大数的存储以及计算。这里使用数组来存储数字即可,数组的每一个元素存储数字的一位。这里使用c++提供的vector容器,比较方便。
#include <iostream>
#include <vector>
using namespace std;
int min(int a, int b) {
if (a > b) { return b; }
else { return a; }
}
vector<int> Vadd(vector<int> v1, vector<int> v2) {
vector<int> result; // 存放加和结果
int length1 = v1.size(); // 长度
int length2 = v2.size();
int len = min(length1, length2); // 找最短的那个
int carry = 0; // 进位
for (int i = 0; i < len; i++) { // 加和前面长度相同的部分
int add_temp = v1[i] + v2[i] + carry; // 当前要加的大小
if (add_temp < 10) { // 小于10不产生进位
result.push_back(add_temp); // 直接加
carry = 0;
}
else {
result.push_back(add_temp % 10); // 产生进位,加模的余数
carry = 1; // 进位变成1
}
}
// 同样的方法加和后面相同的部分
if (carry == 1) {
if (length1 == length2) {
result.push_back(1);
}
else if (len == length1) {
int carry2 = 1;
for (int i = length1; i < length2; i++) {
int add_temp2 = v2[i] + carry2;
if (add_temp2 < 10) {
result.push_back(add_temp2);
carry2 = 0;
}
else {
result.push_back(add_temp2 % 10);
carry2 = 1;
}
}
if (carry2 == 1) {
result.push_back(1);
}
}
else {
int carry2 = 1;
for (int i = length2; i < length1; i++) {
int add_temp2 = v1[i] + carry2;
if (add_temp2 < 10) {
result.push_back(add_temp2);
carry2 = 0;
}
else {
result.push_back(add_temp2 % 10);
carry2 = 1;
}
}
if (carry2 == 1) {
result.push_back(1);
}
}
}
else {
if (len = length1 && length1 != length2) {
for (int i = length1; i < length2; i++) {
result.push_back(v2[i]);
}
}
else if (len = length2 && length1 != length2) {
for (int i = length2; i < length1; i++) {
result.push_back(v1[i]);
}
}
}
return result;
}
void fibo(int n, vector<vector<int>>& storage) {
if (n > 1) {
for (int i = 2; i <= n - 1; i++) {
storage.push_back(Vadd(storage[i - 2], storage[i - 1]));
}
}
}
void printV(vector<int> v) {
int len = v.size();
// vector容器最低位存储的是个位,所以打印需要从后往前打印
for (int i = len - 1; i >= 0; i--) {
cout << v[i];
}
cout << endl;
cout << endl;
}
int main() {
vector<vector<int>> storage;
vector<int> v0; v0.push_back(0);
vector<int> v1; v1.push_back(1);
storage.push_back(v0);
storage.push_back(v1);
fibo(100, storage); // 这里是项数
int len = storage.size();
for (int i = 0; i < len; i++) {
cout << "第" << i + 1 << "项为:";
printV(storage[i]);
}
/*printV(storage[len - 1]);*/
}
这个代码在vector加法函数也有个优化的地方,上面的代码是先加两个数相同长度的部分,然后再去处理较长的数剩余的部分,实际上将较短的数填充0后使其长度和较长的数相同就不需要后面的步骤了。