矩阵快速幂&斐波那契数列

这篇具有很好参考价值的文章主要介绍了矩阵快速幂&斐波那契数列。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

矩阵快速幂&斐波那契数列

矩阵快速幂:

  1. 快速地求出斐波那契数列中的每一项
  2. 可以快速地求出斐波那契数列的前n项的和

首先我们来看如何快速地求出斐波那契数列的第n项

1.快速求斐波那契数列的某一项

F n = [ f n , f n + 1 ] F_n = [f_n,f_{n+1}] Fn=[fn,fn+1],构造这一个行向量,那么对于此,我们思考 F n F_n Fn乘一个什么样的矩阵可以得到 F n + 1 F_{n+1} Fn+1
显然:可以乘一个这样子的矩阵 矩阵快速幂求斐波那契数列,矩阵,算法,线性代数
然后我们对这个递推的操作一直乘矩阵A,就可以推出最终 F n F_n Fn的表达式:
F n = F 0 ∗ A n F_n = F_0 * A^n Fn=F0An,求出 F n F_n Fn之后,自然就得到 f n f_n fn了!

2.快速求斐波那契数列的前n项和

法1

这个其实具体是一个推公式的过程,没有涉及到其他的东西,
S n = f 0 + f 1 + f 2 + . . . + f n S_n = f_0 + f_1 + f_2 +...+f_n Sn=f0+f1+f2+...+fn
具体的公式为:
S n = f n + 2 − f 1 S_n = f_{n+2} - f_1 Sn=fn+2f1 注意在我规定的斐波那契数列中,是从第0项开始的,公式具体的推导如下:
矩阵快速幂求斐波那契数列,矩阵,算法,线性代数
因此若要求斐波那契数列的前n项和,只需要求出 f n + 2 f_{n+2} fn+2即可,那么这个问题其实又回到了求斐波那契数列的第n项,这样来看就很简单啦!

法2

构造一个新的行向量,
F n = [ f n , f n + 1 , S n ] F_n = [f_n,f_{n+1},S_n] Fn=[fn,fn+1,Sn] ,这里的 S n S_n Sn就表示的是前n项的和,那么我们还是像开始一样思考一下如何构造矩阵,使得 F n F_n Fn可以通过递推来求得。很容易推导出矩阵A的形式应该为:
矩阵快速幂求斐波那契数列,矩阵,算法,线性代数
因此我们可以通过此递推得到: F n = F 0 ∗ A n F_n = F_0 * A^{n} Fn=F0An
这样只要我们把 F n F_n Fn求出来,就可以得到结果啦!

习题1:1303. 斐波那契前 n 项和

[1303. 斐波那契前 n 项和 - AcWing题库]:

附上AC代码:文章来源地址https://www.toymoban.com/news/detail-736656.html

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
LL n,m;
const int N = 3;
int a[N][N] = {
    {0,1,0},
    {1,1,1},
    {0,0,1},
};
// 矩阵乘法:计算行向量 * 一个矩阵
void mul(int c[],int a[],int b[][N]){   // 计算 a[] * b[][]  -> 即:f1[] * a[][] 之后的值
    int tmp[N] = {0};    //  表示最后的答案数组
    
    for(int i = 0;i < N;i++){  // i表示答案的那一列
        // c[i] 表示的值应该等于 a中的每一个数 * b中第i列的那个数 的求和
        for(int j = 0;j < N;j++){  // j枚举的就是a中的每一个数
            tmp[i] = (tmp[i] + (LL)a[j] * b[j][i]) % m;
        }
    }
    
    memcpy(c,tmp,sizeof(tmp));
    
}
// 矩阵乘法:计算一个矩阵 * 一个矩阵
void mul(int c[][N],int a[][N],int b[][N]){
    int tmp[N][N] = {0};
    
    for(int i = 0;i < N;i++){
        for(int j = 0;j < N;j++){  // 枚举计算tmp[i][j]
            // 计算c[i][j]需要枚举的就是a[i][]的那一行的数 * b[][j]那一列的数
            for(int k = 0;k < N;k++){
                tmp[i][j] = (tmp[i][j] + (LL)a[i][k] * b[k][j]) % m;
            }
        }
    }
    
    memcpy(c,tmp,sizeof(tmp));
    
}

int main()
{
    cin >> n >> m;
    int f1[N] = {1,1,1};   // 表示的是  [f1,f2,S1]
    // Fn为向量
    // Fn = F1 * A^n-1  次幂
    LL k = n - 1;
    // 写快速幂
    while(k){
        if(k & 1) mul(f1,f1,a);   // f1[] = f1[] * a[][]
        k >>= 1;
        mul(a,a,a);        // a[][] = a[][] * a[][]  
    }
    
    cout << f1[2] << endl;
    return 0;
}

3.快速求斐波那契数列前n项的平方和

如何快速地求出 f 0 2 + f 1 2 + . . . + f n 2 f_0^2 + f_1^2 + ... + f_n^2 f02+f12+...+fn2 呢?
先给出结论: f 0 2 + f 1 2 + . . . + f n 2 = f i ∗ f i + 1 f_0^2 + f_1^2 + ... + f_n^2 = f_i * f_{i + 1} f02+f12+...+fn2=fifi+1
下面给出证明的过程:
矩阵快速幂求斐波那契数列,矩阵,算法,线性代数
其实只要知道了结论,具体做起题目来就简单多了!

习题2:斐波那契的秘密

http://csoj.scnu.edu.cn/problem/S0413

附上AC代码:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 2,mod = 1e9+7;
int a[N][N] = {
    {0,1},
    {1,1},
};
int f0[N];
int backup[N][N];
int t;
int n;
int l1,r1,l2,r2;
void mul(int c[][N],int a[][N],int b[][N]){
    int tmp[N][N] = {0};
    for(int i = 0;i < N;i++){
        for(int j = 0;j < N;j++){
            for(int k = 0;k < N;k++){
                tmp[i][j] = (tmp[i][j] + (LL)a[i][k] * b[k][j]) % mod;
            }
        }
    }
    memcpy(c,tmp,sizeof(tmp));
}
void mul(int c[],int a[],int b[][N]){
    int tmp[N] = {0};
    for(int i = 0;i < N;i++){
        for(int j = 0;j < N;j++){
            tmp[i] = (tmp[i] + (LL)a[j] * b[j][i]) % mod;
        }
    }
    memcpy(c,tmp,sizeof(tmp));
}
LL F(int x){  // 求Fx   Fn = F0 * A^n次幂
    memcpy(a,backup,sizeof(backup));
    f0[0] = f0[1] = n;
    while(x){
        if(x & 1) mul(f0,f0,a);
        x >>= 1;
        mul(a,a,a);
    }
    return (LL)f0[0];
}
LL qmi(LL a,LL k,LL p){
    LL res = 1;
    while(k){
        if(k & 1) res =  res * a % p;
        k >>= 1;
        a = a * a % p;
    }
    return res;
}
int main()
{
    cin >> n;
    int t;
    cin >> t;
    memcpy(backup,a,sizeof(a));
    while(t--){
        cin >> l1 >> r1 >> l2 >> r2;
        // cout << F(l1 - 1) << " " << F(l1) << " " << F(r1) << " "  << F(r1+1) << endl;
        // cout << F(r2 + 2) << " " << F(l2 + 1) << endl;
        LL fenzi = ((F(r1) * F(r1 + 1) % mod - F(l1 - 1) * F(l1) % mod) % mod + mod) % mod;
        // cout << "fenzi = " << fenzi << endl;
        LL fenmu = ((F(r2 + 2) - F(l2 + 1)) % mod + mod) % mod;
        // 然后求逆元
        LL fenmu2 = qmi(fenmu,mod-2,mod);
        // cout << "分母 = " << fenmu2 << endl;
        cout << fenzi * fenmu2 % mod << endl;
    }
    return 0;
}

到了这里,关于矩阵快速幂&斐波那契数列的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言实现求解斐波那契数列的四种方法及优化处理(递归,迭代,特殊性质公式,矩阵快速幂)

            众所周知, 斐波那契数列 是非常经典的一个数列,它的数学公式如下         为了便于观察,我们列出它的几项:0  1  1  2  3  5  8  13  21......         下面我们将介绍四种方法来用C语言计算机代码实现对斐波那契数列的求解,分别是:递归法,迭代法

    2023年04月09日
    浏览(35)
  • 【算法】斐波那契数列通项公式

    如果数列 a n a_n a n ​ 的递推公式: a n = c 1 a n − 1 + c 2 a n − 2 a_n=c_1a_{n-1}+c_2a_{n-2} a n ​ = c 1 ​ a n − 1 ​ + c 2 ​ a n − 2 ​ ------(1) 根据待定系数法,假设 a n − x a n − 1 = y ( a n − 1 − x a n − 2 ) a_n-xa_{n-1}=y(a_{n-1}-xa_{n-2}) a n ​ − x a n − 1 ​ = y ( a n − 1 ​ − x a n − 2 ​

    2023年04月24日
    浏览(45)
  • 【算法学习】斐波那契数列模型-动态规划

            我在算法学习过程中,针对斐波那契数列模型的动态规划的例题进行了一个整理,并且根据标准且可靠一点的动态规划解题思路进行求解类似的动归问题,来达到学习和今后复习的必要。         所谓的斐波那契数列模型,即当前状态的值等于前两种状态的值之和。

    2024年02月04日
    浏览(54)
  • 【算法】斐波那契数列与台风的故事

    在小岛的一个海滨小镇上,住着一个名叫苏菲的女孩。苏菲一家人靠海为生,她的生活简单而朴素,与大自然和谐共生。每天,苏菲都会来到海边,欣赏那美丽的日出和日落,感受着大海的呼吸。 然而,小岛的美丽风光并非一成不变。每年夏季,热带气旋活跃,台风频繁登陆

    2024年02月10日
    浏览(40)
  • C语言经典算法实例6:斐波那契数列

    斐波那契数列指的是这样一个数列:1,1,2,3,5,8,13,21,34,55,89… 这个数列从第3项开始,每一项都等于前两项之和。 斐波那契数列的定义者,是意大利数学家莱昂纳多·斐波那契(Leonardo Fibonacci),生于公元1170年,卒于1250年,籍贯是比萨。 他被人称作“比萨的莱昂

    2024年02月02日
    浏览(44)
  • 【算法优选】 动态规划之斐波那契数列模型

    动态规划相关题目都可以参考以下五个步骤进行解答: 状态表⽰ 状态转移⽅程 初始化 填表顺序 返回值 后面题的解答思路也将按照这五个步骤进行讲解。 泰波那契序列 Tn 定义如下: T0 = 0, T1 = 1, T2 = 1, 且在 n = 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2 给你整数 n,请返回第 n 个泰波那契

    2024年02月05日
    浏览(55)
  • C++算法 —— 动态规划(1)斐波那契数列模型

    每一种算法都最好看完第一篇再去找要看的博客,因为这样会帮你梳理好思路,看接下来的博客也就更轻松了。当然,我也会尽量在写每一篇时都可以让不懂这个算法的人也能边看边理解。 动规的思路有五个步骤,且最好画图来理解细节,不要怕麻烦。当你开始画图,仔细阅

    2024年02月10日
    浏览(44)
  • 一分钟学算法-递归-斐波那契数列递归解法及优化

    一分钟学一个算法题目。 今天我们要学习的是用递归算法求解斐波那契数列。 视频教程链接:https://www.bilibili.com/video/BV1Wu4y1i7JJ/ 首先我们要知道什么是斐波那契数列。 斐波那契数列,又称黄金分割数列,是一个经典的数学数列,其特点是第一项,第二项为1,后面每个数字都

    2024年02月11日
    浏览(48)
  • 递归以及斐波那契数列递归算法和迭代算法的实现与分析

    程序调用自身的编程技巧称为递归( recursion) 递归有两个过程,简单地说一个是 递的过程 ,一个是 归的过程 。 递归的两个必要条件 1. 存在限制条件 ,当满足这个限制条件的时候,递归便不再继续。 2.每次递归调用之后越来越 接近这个限制条件 . 递归本质就是函数调用

    2024年02月12日
    浏览(37)
  • Java数据结构与算法:动态规划之斐波那契数列

    大家好,我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编。在这寒冷的季节里,让我们一同探讨Java中的动态规划,重点关注解决问题的经典代表之一——斐波那契数列。 动态规划简介 动态规划是一种解决问题的数学方法,通常用于优化递归算法。它通过将问

    2024年01月22日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包