求斐波那契数列矩阵乘法的方法

斐波那契数列

先来简单介绍一下斐波那契数列:
斐波那契数列是指这样一个数列:1,1,2,3,5,8,13,21,34,55,89……这个数列从第3项开始 ,每一项都等于前两项之和。

现在要求斐波那契数列的第n项,如果用Java代码层面来讲就是下面这样。

一个for循环,声明一个变量累加到第n项即可。 O ( N ) O(N) O(N)的时间复杂度。但这并不是最优解,最优解的时间复杂度是 O ( L o g N ) O(LogN) O(LogN)

最优解怎么得到的?是根据上面斐波那契数列的递推式: F ( n ) = F ( n − 1 ) + F ( n − 2 ) F(n) = F(n - 1) + F(n - 2) F(n)=F(n1)+F(n2)

这是一项严格的递推式,在告诉初始值的情况下,如果后面的每一项都按照严格的递推式可以推出来,那都有 O ( L o g N ) O(LogN) O(LogN)的方法

那什么没有 O ( L o g N ) O(LogN) O(LogN)的方法呢? 比如说有一个左数列。得到这个左数列的第n项。

给定的信息比如有一个 boolean[] b = {T , T , F , F , T , T , T}。 对于左数列来说,第一项是1,第二项也是1,之后的每一项根据是T还是F来进行表达。 如果当前项是 F ,则 F ( n ) = F ( n − 1 ) F(n) = F(n - 1) F(n)=F(n1) ,如果当前项是 T,则 F ( n ) = F ( n − 1 ) + F ( n − 2 ) F(n) = F(n - 1) + F(n - 2) F(n)=F(n1)+F(n2)。以此来决定下一项值是什么。

所以根据公式:第三项 = 1,第四项 = 1,第五项 = 2 以此类推…。这种就没有 O ( L o g N ) O(LogN) O(LogN)的方法,因为会根据不同的条件进行条件转移。

斐波那契数列就是没有条件转移的严格递推式。这种都有 O ( L o g N ) O(LogN) O(LogN)的方法


线性代数

如果 F ( n ) = F ( n − 1 ) + F ( n − 2 ) F(n) = F(n - 1) + F(n - 2) F(n)=F(n1)+F(n2),第n项和 F(n - 1) 和 F(n - 2)是严格关系,那在公式中,减的最多的常数是2,那就可以说它是一个二阶递推,依然是以斐波那契数列来举例。

已知斐波那契数列的第一项 F(1) = 1,第二项 F(2) = 1,那一定会存在下面这个关系:
∣ F 3 , F 2 ∣ = ∣ F 2 , F 1 ∣ × ∣ a b c d ∣ |F_3,F_2| = |F_2,F_1| \times\left| \begin{matrix} a & b \\ c & d \end{matrix} \right| F3,F2=F2,F1× acbd
没有为什么,龟腚!

同样的,斐波那契数列的第四项F(4)和第三项F(3) 的行列式一定等于下面的式子(abcd为相同的2 * 2矩阵)。
∣ F 4 , F 3 ∣ = ∣ F 3 , F 2 ∣ × ∣ a b c d ∣ |F_4,F_3| = |F_3,F_2| \times\left| \begin{matrix} a & b \\ c & d \end{matrix} \right| F4,F3=F3,F2× acbd

那这个2 * 2矩阵的abcd是什么呢? 接下来我们算一下

因为斐波那契数列的前几项我们都是已知的,所以可以先列出来:
F(1) = 1, F(2) = 1,F(3) = 2,F(4) = 3,接下来我们带入到式子中。

∣ F 3 , F 2 ∣ = ∣ F 2 , F 1 ∣ × ∣ a b c d ∣ − > ∣ 2 , 1 ∣ = ∣ 1 , 1 ∣ × ∣ a b c d ∣ |F_3,F_2| = |F_2,F_1| \times\left| \begin{matrix} a & b \\ c & d \end{matrix} \right| ->|2,1| = |1,1| \times\left| \begin{matrix} a & b \\ c & d \end{matrix} \right| F3,F2=F2,F1× acbd >∣2,1∣=∣1,1∣× acbd

矩阵乘法:
F 2 ∗ a + F 1 ∗ c = F 3 F_2 * a + F_1 * c = F_3 F2a+F1c=F3 F 2 ∗ b + F 1 ∗ d = F 2 F_2 * b + F_1 * d = F_2 F2b+F1d=F2

带入进来就是 :
{ a + c = 2 b + d = 1 (1) \begin{cases} a + c = 2 \\ b + d = 1 \end{cases} \tag{1} {a+c=2b+d=1(1)
一个式子不够,求不出来,再次带入下一个公式:
∣ F 4 , F 3 ∣ = ∣ F 3 , F 2 ∣ × ∣ a b c d ∣ − > ∣ 3 , 2 ∣ = ∣ 2 , 1 ∣ × ∣ a b c d ∣ |F_4,F_3| = |F_3,F_2| \times\left| \begin{matrix} a & b \\ c & d \end{matrix} \right|->|3,2| = |2,1| \times\left| \begin{matrix} a & b \\ c & d \end{matrix} \right| F4,F3=F3,F2× acbd >∣3,2∣=∣2,1∣× acbd

矩阵乘法:
F 3 ∗ a + F 2 ∗ c = F 4 F_3 * a + F_2 * c = F_4 F3a+F2c=F4 F 3 ∗ b + F 2 ∗ d = F 3 F_3 * b + F_2 * d = F_3 F3b+F2d=F3

带入进来就是 :
{ 2 a + c = 3 2 b + d = 2 (2) \begin{cases} 2a + c = 3 \\ 2b + d = 2 \end{cases} \tag{2} {2a+c=32b+d=2(2)
求出:a = 1 , b = 1, c = 1 ,d = 0

再次带入验证一下:
∣ F 5 , F 4 ∣ = ∣ F 4 , F 3 ∣ × ∣ a b c d ∣ − > ∣ F 5 , F 4 ∣ = ∣ 3 , 2 ∣ × ∣ 1 1 1 0 ∣ |F_5,F_4| = |F_4,F_3| \times\left| \begin{matrix} a & b \\ c & d \end{matrix} \right|->|F_5,F_4| = |3,2| \times\left| \begin{matrix} 1 & 1 \\ 1 & 0 \end{matrix} \right| F5,F4=F4,F3× acbd >F5,F4=∣3,2∣× 1110

矩阵乘法:
F 4 ∗ a + F 3 ∗ c = F 5 F_4 * a + F_3 * c = F_5 F4a+F3c=F5 F 4 ∗ b + F 3 ∗ d = F 4 F_4 * b + F_3 * d = F_4 F4b+F3d=F4

3 + 2 = 5 3 + 2 =5 3+2=5 3 + 0 = 3 3 + 0 = 3 3+0=3
求出:F(5) = 5 , F(4) = 3。 证明我们求出的a,b,c,d是对的。

根据上面的公式可以列出:
{ ∣ F 3 , F 2 ∣ = ∣ F 2 , F 1 ∣ × ∣ 矩阵 ∣ ∣ F 4 , F 3 ∣ = ∣ F 3 , F 2 ∣ × ∣ 矩阵 ∣ ∣ F 5 , F 4 ∣ = ∣ F 4 , F 3 ∣ × ∣ 矩阵 ∣ . . . . . ∣ F n , F n − 1 ∣ = ∣ F n − 1 , F n − 2 ∣ × ∣ 矩阵 ∣ \begin{cases} |F_3,F_2| = |F_2,F_1| \times |矩阵|\\ |F_4,F_3| = |F_3,F_2| \times|矩阵|\\ |F_5,F_4| = |F_4,F_3| \times |矩阵|\\ .....\\ |F_n,F_{n-1}| = |F_{n-1},F_{n-2}| \times|矩阵| \end{cases} F3,F2=F2,F1×矩阵F4,F3=F3,F2×矩阵F5,F4=F4,F3×矩阵.....Fn,Fn1=Fn1,Fn2×矩阵

推导一下,将相同的值带入可得出:
∣ F n , F n − 1 ∣ = ∣ F 2 , F 1 ∣ × ∣ 相同矩阵 ∣ n − 2 |F_n,F_{n-1}| = |F_2,F_1| \times\left| \begin{matrix} 相同矩阵 \end{matrix} \right|^{n-2} Fn,Fn1=F2,F1× 相同矩阵 n2

再次回到求斐波那契数列第n项的问题。

我们目前已经推导出了最后的公式,那想要求斐波那契数列第n项的关键点是不是在于求矩阵的n - 2次方,只要矩阵的某次方算的足够快,第n项是不是求的就足够快!!!!


如何让一个数的次方算的足够快

在求得矩阵某次方之前,我们先来看看如何让一个普通的数,比如说 1 0 75 10^{75} 1075这个数算的足够快?

先来搞定这个数,相同的逻辑用在矩阵上,那同样矩阵也会非常快!

利用二进制!

1 0 75 10^{75} 1075如果是75个10相乘,那这是一个 O ( N ) O(N) O(N)的问题,不够快。

首先,将幂数75拆分成对应的二进制为01001011(64 + 8 + 2 + 1 ),再让变量 t = 1 0 1 10^1 101,t不断的和自己相乘变成 1 0 2 10^2 102 1 0 4 10^4 104 1 0 8 10^8 108… t 不断的追赶75不断的和自己相乘,那追赶75的一共追赶多少次? O ( L o g N ) O(LogN) O(LogN)次。

接下来将 变量t 和75的二进制进行融合。

t 没和自己相乘之前,是 1 0 1 10^1 101,我们总的结果 result,一开始是1,这时候看01001011,二进制中1的位置是有值的,说明这个值是我结果需要的,那就用 result * t ( 1 0 1 10^1 101)
在这里插入图片描述

再接着往下来,01001011中2的位置也是1,代表这个位置也是结果需要的,将此时的 t 也乘进来。
在这里插入图片描述
继续往下,此时来到了01001011中的4,4的二进制为0,代表结果不被需要,不需要就不乘这个数,t继续和自己相乘。
在这里插入图片描述
继续向下来到了01001011中的8。同样也是被需要的,将 1 0 8 10^8 108加到结果中。
在这里插入图片描述
依次类推,继续向下,16 32 对应的2进制位置都为0,都不需要这两个数,直到来到了 1 0 64 10^{64} 1064次方,将需要的数都乘到结果中,就是最终答案。
在这里插入图片描述
t 在不断和自己相乘的过程中,按位判断,要不要添加到结果中去。

为什么这么做?

其实追根究底是一个二分的过程,只不过自己二分的过程没有二进制提供的优良。


求一个数字的n次方我们已经解决了 ,那矩阵呢? 同理!

求一个矩阵的75次方

将矩阵的幂数进行二进制拆分,那在求 1 0 75 10^{75} 1075时,先搞了result = 1,如果这个数被需要,就乘到结果中,那换到矩阵中,是不是只要将result 的 1 变成矩阵中代表 1 的数就行了。t 同样也是变成 矩阵的 1次方, 矩阵的2次方,不断和自己相乘。

单位矩阵

单位矩阵中对角线上都是1剩下位置都是0就代表着1 。
∣ 1 0 0 0 1 0 0 0 1 ∣ \left| \begin{matrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{matrix} \right| 100010001

矩阵乘法

  1. 当矩阵A的列数等于矩阵B的行数时,A与B可以相乘。

  2. 矩阵C的行数等于矩阵A的行数,C的列数等于B的列数。

  3. 乘积C的第m行第n列的元素等于矩阵A的第m行的元素与矩阵B的第n列对应元素乘积之和

所以:A是一个 m × n 的矩阵,B是一个 n × p 的矩阵,C是一个 m × p 的矩阵。
∣ 1 2 3 4 ∣ ∗ ∣ 5 6 7 8 ∣ = ∣ 1 ∗ 5 + 2 ∗ 7 1 ∗ 6 + 2 ∗ 8 3 ∗ 5 + 4 ∗ 7 3 ∗ 6 + 4 ∗ 8 ∣ \left| \begin{matrix} 1 & 2 \\ 3 & 4 \\ \end{matrix} \right| * \left| \begin{matrix} 5 & 6 \\ 7 & 8 \end{matrix} \right|= \left| \begin{matrix} 1 * 5 + 2 * 7 & 1 * 6 + 2* 8 \\ 3 * 5 + 4 * 7 & 3 * 6 + 4 * 8 \end{matrix} \right| 1324 5768 = 15+2735+4716+2836+48

代码
因为是两个矩阵相乘,2 * 2的矩阵相得到的也一定是个2 * 2的矩阵,要求的是第F(n)项,根据上面的公式可以得出
F n = F 1 ∗ a + F 2 ∗ c Fn = F_1 * a + F_ 2 * c Fn=F1a+F2c 。 F(1) = 1 F2 = (1) ,所以我们最终结果只需要 res[0][0] + res[1][0] 即可。

 public static int f2(int n){
        if (n == 0){
            return 0;
        }

        if (n == 1 || n == 2){
            return 1;
        }
		//斐波那契数列的单位矩阵
        int[][] base = {{1,1},
                        {1,0}};

        int[][] res = matrixPower(base,n - 2);

        return res[0][0] + res[1][0];
    }

    public static int[][] matrixPower(int[][] m, int p) {
        int[][] res = new int[m.length][m[0].length];
        for (int i = 0; i < res.length; i++) {
            res[i][i] = 1;
        }
        // res = 矩阵中的1
        int[][] t = m;// 矩阵1次方
        for (; p != 0; p >>= 1) {
            if ((p & 1) != 0) {
                res = product(res, t);
            }
            t = product(t, t);
        }
        return res;
    }

    // 两个矩阵乘完之后的结果返回
    public static int[][] product(int[][] a, int[][] b) {
        int n = a.length;
        int m = b[0].length;
        int k = a[0].length; // a的列数同时也是b的行数
        int[][] ans = new int[n][m];
        for(int i = 0 ; i < n; i++) {
            for(int j = 0 ; j < m;j++) {
                for(int c = 0; c < k; c++) {
                    ans[i][j] += a[i][c] * b[c][j];
                }
            }
        }
        return ans;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/321046.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

webstorm最新版 激活 成功了

使用webstorm开发工具 很完美&#xff0c;第一次用webstorm IDE 开发工具就完美的激活了&#xff0c;你也不妨试试 链接地址&#xff1a;http://mano100.cn/thread-1942-1-1.html 激活后如下

DM数据库安装注意事项

数据库安装注意事项 一、安装前 一些参数需要在数据库创建实例前找用户确认。 参数名参数掩码参数值备注数据页大小PAGE_SIZE32数据文件使用的页大小(缺省使用8K&#xff0c;建议默认&#xff1a;32)&#xff0c;可以为 4K、8K、16K 或 32K 之一&#xff0c;选择的页大小越大…

Linux常用命令之cp、rm、touch、mv

cp: 复制文件或目录 -f 覆盖目标同名文件或目录时不进行提醒&#xff0c;而直接强制复制。-i 覆盖目标同名文件或目录时提醒用户确认。-p 复制时保持源文件的权限、属主及时间标记等属性不变&#xff08;默认权限属主是变化的&#xff09;。-r 复制目录时必须使用此选项&a…

Nacos注册中心-安装

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、认识Nacos二、安装Nacos1.直接方法nacos.io&#xff0c;点击view onGithub2.点击Releases3、点击Tags&#xff0c;可以看见所有版本&#xff0c;建议下载1.…

Baumer工业相机堡盟工业相机如何使用OpenCV实现相机图像的显示(C#)

Baumer工业相机堡盟工业相机如何使用OpenCV实现相机图像的显示&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机的图像转换为OpenCV的Mat图像的技术背景在NEOAPI SDK里使用OpenCV实现相机图像的显示联合OpenCV实现相机图像的显示测试演示图 工业相机通过使用OpenCV实现…

史诗级长文--朴素贝叶斯

引言 朴素贝叶斯算法是有监督的学习算法&#xff0c;解决的是分类问题&#xff0c;如客户是否流失、是否值得投资、信用等级评定等多分类问题。该算法的优点在于简单易懂、学习效率高、在某些领域的分类问题中能够与决策树、神经网络相媲美。但由于该算法以自变量之间的独立&am…

java: 5-6 break

文章目录 1. break1.1 介绍1.2 语法和流程图1.3 入门练习1.4 细节说明1.5 练习 【老韩视频p137-】 1. break 看个需求&#xff1a;随机生成 1-100 的一个数&#xff0c;直到生成了 97 这个数&#xff0c;看看你一共用了几次? 【思路分析:循环&#xff0c;但是循环的次数不知道…

VQE音频处理流程

VQE 上行VQE&#xff0c;主要针对MIC采集部分的音频增强 下行VQE&#xff0c;主要针对SPK播放部分的音频增强 附关键词解释 RES RES 模块为重采样&#xff08;Resampler&#xff09;模块。当AI上行或AO下行通路中开启VQE 各功能 模块时&#xff0c;在处理前后各存在一次重采样…

实战之-Redis代替session实现用户登录

一、设计key的结构 首先我们要思考一下利用redis来存储数据&#xff0c;那么到底使用哪种结构呢&#xff1f;由于存入的数据比较简单&#xff0c;我们可以考虑使用String&#xff0c;或者是使用哈希&#xff0c;如下图&#xff0c;如果使用String&#xff0c;注意他的value&…

计算机网络技术-2022期末考试解析

【前言】 这是计算机网络技术这门课&#xff0c;感觉和计网还是有不一样的&#xff0c;但也有能做的&#xff0c;把能做的做了。 一、单项选择题&#xff08;每题2分&#xff0c;共20分&#xff09; 1. 用于测试两台计算机连通状况的命令是 。 ( ) A. cmd B. ping C. ipconf…

代码随想录day30 回溯算法最终章

51. N皇后 题目 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回所有不同的 n 皇后问题 的解决方案。 每一种解法包含一个不同的 n 皇后问题 的棋子放置方案&#xff0c;该方案中 Q 和…

TIFF转JPG助手:轻松批量转换,优化图片管理

在数字时代&#xff0c;图片已成为我们生活和工作中不可或缺的一部分。为了更好地管理和使用这些图片&#xff0c;我们需要一个强大的工具来帮助我们转换和优化图片格式。TIFF转JPG助手正是这样一款理想的解决方案 首先&#xff0c;我们进入首助编辑高手主页面&#xff0c;会看…

嵌入式软件面试之程序在存储器中的分布

Hi, 大家好&#xff0c;今天阿目分享的是一个嵌入式软件面试的常见问题&#xff0c;内存分布或者说程序在内存中的布局&#xff0c;我们写的程序是按照怎么的准则放在内存中的&#xff1f; 一般有操作系统的嵌入式设备&#xff0c;都会有一个Bootloader, 它负责在上电后初始化…

70.网游逆向分析与插件开发-角色数据的获取-自动化助手UI显示角色数据

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;利用技能点属性分析角色数据基址-CSDN博客 码云地址&#xff08;ui显示角色数据 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&#xff1a;367aa71f60b…

HCIP之OSPF大实验

华子目录 实验拓扑及要求实验步骤合理划分网段配置IP地址两个area 0区域可以访问公网首先使用ospf使私网通在边界路由器上写静态缺省在边界路由器上做nat&#xff0c;实现公网访问在边界路由器上强制下放缺省 使用GRE连接两个area 0&#xff0c;解决不规则区域划分在边界路由器…

【Vue3】2-11 : 生命周期钩子函数及原理分析

本书目录&#xff1a;点击进入 一、组件生命周期概述 1.1 官方生命周期 1.2 钩子函数&#xff08;回调函数&#xff09; ▶ 生命周期可划分为三个部分(- >表示执行循序)&#xff1a; 二、实战&#xff1a;测试生命周期流程 &#xff1e; 代码 &#xff1e; 效果 一…

(十二)EEPROM的补充

文章目录 EEPROM补充篇读EEPROM补充内容写EEPROM补充内容单字节写入多字节拆成单字节写入现象 EEPROM补充篇 读EEPROM补充内容 对于上一篇博文在读EEPROM的时候&#xff0c;提到的DUMMY WRITE&#xff1a; 这里怎么理解呢&#xff1a; 大家看&#xff0c;写EEPROM的逻辑除了…

MySQl Mybatis

一、MySQL 1.1 概述 1.1.1 MySQL安装 1.1.2 数据模型 1.1.3 SQL简介 1.2 DDL 1.2.1 数据库操作 1.2.2 图形化工具 1.2.3 表结构操作 &#xff08;一&#xff09;创建 &#xff08;二&#xff09;数据类型 &#xff08;1&#xff09;数值类型 age tinyint unsigned——加上…

技术阅读周刊第十四期:Golang 作者 Rob Pike 在 GopherConAU 上的分享

技术阅读周刊&#xff0c;每周更新。 历史更新 20231215&#xff1a;第十期20231122&#xff1a;第十一期20231129&#xff1a;第十二期20240105&#xff1a;第十三期&#xff1a;一些提高生产力的终端命令 What We Got Right, What We Got Wrong URL: https://commandcenter.b…

pinyin-pro库使用方式

pinyin-pro 是一个专业的 JavaScript 中文转拼音的库&#xff0c;具备多音字识别准确、体积轻量、性能优异、功能丰富等特点。 pinyin-pro官网链接&#xff1a;介绍 | pinyin-pro 运行展示 pinyin-pro安装命令&#xff1a; # 选择一个你使用的包管理器进行安装即可# NPM $ n…