【斐波那契】原来困扰多年的生兔子问题竟然能够轻松拿捏...万能公式法...

本文主要是介绍【斐波那契】原来困扰多年的生兔子问题竟然能够轻松拿捏...万能公式法...,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上篇文章我们讲解了「矩阵快速幂」技巧,通过快速幂极大的优化了 斐波那契数列 的求解问题。并且通过分析知道了 系数矩阵 是解决问题的关键。

本文我们继续深化对于 系数矩阵 的求解,介绍一种通用方法,一举解决所有 斐波那契及变种类型 的问题。

提示: 先看 上篇文章 效果更佳哦~

生兔子问题

有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不会死,问第 N 月有多少对兔子?

这道题不是典型的斐波那契数列么,递推公式为:

这和上道题目一模一样,根本不需要讲解。但是,我们对于本题进行一定的改编,增加点儿难度


假设,现有一对成熟的兔子,新出生的兔子从出生的 第 4 个月 开始每月生一对兔子,问第 N 月有多少对兔子呢?

注意:

  1. 第一月已经有成熟的兔子了,所以从第二月开始就有新的兔子诞生了。
  2. 新出生的兔子三个月后才会生新的兔子。

通过分析不难发现:

因此,递推表达式为:

(如果这样不容易想出来,也可以自己动手列举列举,多写几项就能观察出规律啦)

关系推导

按照 上篇文章 的思路,我们做如下推导:

温馨提示:先看上篇文章更好理解哦~

三个相邻项 写成矩阵形式,由此可以得到关系式:

因此系数矩阵就得到了,后续的求解和上篇文章的简直一模一样了~

-----------------------桥豆麻袋---------------------

有小伙伴说了,这个系数矩阵不太会搞出来啊,那怎么办呢?有什么无脑办法么…哎,还真有!

这就要拿出我们初中就学过的万能的 待定系数法 了。

不就是一个系数矩阵嘛,我直接全设成未知数,一个一个解出来不就行了~

九个未知数,需要九个式子:

虽然看着麻烦,其实解起来也还行吧~哈哈哈,这样我们依然能够得到系数矩阵。

有了系数矩阵之后,就可以将第 n 项化简成只与前 3 项有关的式子。

即系数矩阵的 n-3 次方的第一行与 F3, F2, F1 的内积和。

代码

public static int f(int n) {if (n < 1) {return 0;}if (n == 1 || n == 2 || n == 3) {return n;}int[][] base = { { 1, 0, 1 }, { 1, 0, 0 }, { 0, 1, 0 } };int[][] res = matrixPower(base, n - 3);return 3 * res[0][0] + 2 * res[0][1] + res[0][2];
}private 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;}int[][] t = m;for (; p != 0; p >>= 1) {if ((p & 1) != 0) {res = produce(res, t);}t = produce(t, t);}return res;
}private static int[][] produce(int[][] a, int[][] b) {int n = a.length;int m = b[0].length;int k = a[0].length;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;
}

只需在上篇文章代码中,将 f() 函数中初始边界条件、系数矩阵 以及 次方数和返回结果进行修改即可,另外两个函数无需做任何改变(具体细节可以参考 上篇文章 哦~)。

总结

通过本文的探讨,再次验证了 求解系数矩阵 就是解决此类斐波那契递推的关键。我们可以将结论进行适当推广:

当递推式是关于 F(n) 直到 F(n-i) 的,那么就可以将 i 项组合成一个矩阵,进行求解,此时需要构造一个 i*i 的系数矩阵,最终答案与 n-i 次方i 项已知项的内积 有关。


学习到这里,我们就得到了 斐波那契类型题万能解法 了,稍微有点难度哦 ~~~ 点赞、转发让你的小伙伴们一起来学吧!!!

~ 点赞 ~ 关注 ~ 星标 ~ 不迷路 ~!!!

关注回复「ACM紫书」获取 ACM 算法书籍~

这篇关于【斐波那契】原来困扰多年的生兔子问题竟然能够轻松拿捏...万能公式法...的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/938652

相关文章

mybatis和mybatis-plus设置值为null不起作用问题及解决

《mybatis和mybatis-plus设置值为null不起作用问题及解决》Mybatis-Plus的FieldStrategy主要用于控制新增、更新和查询时对空值的处理策略,通过配置不同的策略类型... 目录MyBATis-plusFieldStrategy作用FieldStrategy类型每种策略的作

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

Python Jupyter Notebook导包报错问题及解决

《PythonJupyterNotebook导包报错问题及解决》在conda环境中安装包后,JupyterNotebook导入时出现ImportError,可能是由于包版本不对应或版本太高,解决方... 目录问题解决方法重新安装Jupyter NoteBook 更改Kernel总结问题在conda上安装了

pip install jupyterlab失败的原因问题及探索

《pipinstalljupyterlab失败的原因问题及探索》在学习Yolo模型时,尝试安装JupyterLab但遇到错误,错误提示缺少Rust和Cargo编译环境,因为pywinpty包需要它... 目录背景问题解决方案总结背景最近在学习Yolo模型,然后其中要下载jupyter(有点LSVmu像一个

解决jupyterLab打开后出现Config option `template_path`not recognized by `ExporterCollapsibleHeadings`问题

《解决jupyterLab打开后出现Configoption`template_path`notrecognizedby`ExporterCollapsibleHeadings`问题》在Ju... 目录jupyterLab打开后出现“templandroidate_path”相关问题这是 tensorflo

如何解决Pycharm编辑内容时有光标的问题

《如何解决Pycharm编辑内容时有光标的问题》文章介绍了如何在PyCharm中配置VimEmulator插件,包括检查插件是否已安装、下载插件以及安装IdeaVim插件的步骤... 目录Pycharm编辑内容时有光标1.如果Vim Emulator前面有对勾2.www.chinasem.cn如果tools工

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

Java多线程父线程向子线程传值问题及解决

《Java多线程父线程向子线程传值问题及解决》文章总结了5种解决父子之间数据传递困扰的解决方案,包括ThreadLocal+TaskDecorator、UserUtils、CustomTaskDeco... 目录1 背景2 ThreadLocal+TaskDecorator3 RequestContextH

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明

关于最长递增子序列问题概述

《关于最长递增子序列问题概述》本文详细介绍了最长递增子序列问题的定义及两种优化解法:贪心+二分查找和动态规划+状态压缩,贪心+二分查找时间复杂度为O(nlogn),通过维护一个有序的“尾巴”数组来高效... 一、最长递增子序列问题概述1. 问题定义给定一个整数序列,例如 nums = [10, 9, 2