【递归与递推 3】AcWing 717. 简单斐波那契(求解斐波那契数列的若干方法)

简介: 【递归与递推 3】AcWing 717. 简单斐波那契(求解斐波那契数列的若干方法)

Description

以下数列 0 1 1 2 3 5 8 13 21 ... 被称为斐波纳契数列。

这个数列从第 33 项开始,每一项都等于前两项之和。

输入一个整数 N,请你输出这个序列的前 N 项。

输入格式

一个整数 N。

输出格式

在一行中输出斐波那契数列的前 N 项,数字之间用空格隔开。

数据范围

0 < N < 46

输入样例:

5

输出样例:

0 1 1 2 3
难度: 中等
时/空限制 1s / 64MB

递归版本

#include<iostream>
using namespace std;
int main()
{
    long long f[50];
    int n;
    cin >> n;
    f[1] = 0;
    f[2] = 1;
    for(int i = 3; i <= n;i ++)
        f[i] = f[i - 1] + f[i - 2];
    for(int i = 1;i <= n;i ++)
        cout << f[i] << ' ';
    return 0;
}

递推版本

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
    int n;
    cin>>n;
    int a = 0,b = 1;
    for(int i = 1;i <= n;i ++)
    {
        cout<< a << ' ';
        int fn = a + b;
        a = b, b = fn;
    }
    return 0;
}

算法模板

首先定义斐波那契数列问题:

递归

const int MOD = 1000000007;
int f(int n)
{
    if (n <= 1) return 1;
    return (f(n - 1) + f(n - 2)) % MOD;
}

记忆化搜索

const int N = 100000, MOD = 1000000007;
int a[N];
int f2(int n)
{
    if (a[n]) return a[n];
    if (n <= 1) return 1;
    a[n] = f2(n - 1) + f2(n - 2);
    a[n] %= MOD;
    return a[n];
}

递推

const int N = 100000000, MOD = 1000000007;
int f3(int n)
{
    a[0] = a[1] = 1;
    for (int i = 2; i <= n; i ++ )
    {
        a[i] = a[i - 1] + a[i - 2];
        a[i] %= MOD;
    }
    return a[n];
}

递推+滚动变量

仔细观察我们会发现,递推时我们只需要记录前两项的值即可,没有必要记录所有值,所以我们可以用滚动变量递推。

时间复杂度还是 O(n),但空间复杂度变成了 O(1) 。

const int MOD = 1000000007;
int f4(int n)
{
    int x, y, z;
    x = y = 1;
    for (int i = 2; i <= n; i ++ )
    {
        z = (x + y) % MOD;
        x = y;
        y = z;
    }
    return z;
}

矩阵运算 + 快速幂

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <ctime>
using namespace std;
const int MOD = 1000000007;
void mul(int a[][2], int b[][2], int c[][2])
{
    int temp[][2] = {{0, 0}, {0, 0}};
    for (int i = 0; i < 2; i ++ )
        for (int j = 0; j < 2; j ++ )
            for (int k = 0; k < 2; k ++ )
            {
                long long x = temp[i][j] + (long long)a[i][k] * b[k][j];
                temp[i][j] = x % MOD;
            }
    for (int i = 0; i < 2; i ++ )
        for (int j = 0; j < 2; j ++ )
            c[i][j] = temp[i][j];
}
int f_final(long long n)
{
    int x[2] = {1, 1};
    int res[][2] = {{1, 0}, {0, 1}};
    int t[][2] = {{1, 1}, {1, 0}};
    long long k = n - 1;
    while (k)
    {
        if (k&1) mul(res, t, res);
        mul(t, t, t);
        k >>= 1;
    }
    int c[2] = {0, 0};
    for (int i = 0; i < 2; i ++ )
        for (int j = 0; j < 2; j ++ )
        {
            long long r = c[i] + (long long)x[j] * res[j][i];
            c[i] = r % MOD;
        }
    return c[0];
}
int main()
{
    long long n ;
    cin >> n;
    cout << f_final(n) << endl;
    return 0;
}

快速幂算法模板

int qmi(int m, int k, int p)
{
    int res = 1 % p, t = m;
    while (k)
    {
        if (k&1) res = res * t % p;
        t = t * t % p;
        k >>= 1;
    }
    return res;
}
相关文章
|
存储 算法
蓝桥杯:递归 与 例题:斐波那契数列及优化与应用
蓝桥杯:递归 与 例题:斐波那契数列及优化与应用
79 0
|
6月前
|
算法
动态规划求解超详细介绍 例题+代码
动态规划求解超详细介绍 例题+代码
|
6月前
递归求解汉诺塔问题(超详解)
递归求解汉诺塔问题(超详解)
汉诺塔?爬楼梯?斐波那契?知道递归就够了
汉诺塔?爬楼梯?斐波那契?知道递归就够了
97 0
|
机器学习/深度学习 算法
斐波拉契数列的递推递归求解算法
斐波拉契数列的递推递归求解算法
109 0
(蓝桥杯)递推与递归,前缀和,二分经典例题分析
(蓝桥杯)递推与递归,前缀和,二分经典例题分析
(蓝桥杯)递推与递归,前缀和,二分经典例题分析