浅谈矩阵加速——以时间复杂度为O(log n)的算法实现裴波那契数列第n项及前n之和使用矩阵加速法的优化求法
首先请连矩阵乘法乘法都还没有了解的同学简单看一下这篇博客:
https://blog.csdn.net/weixin_44049566/article/details/88945949
首先直接暴力求使用O(n)的时间复杂度肯定是不行的,所以我们应该使用更优的时间复杂度。
设f(n)为裴波那契数列第n项。让我们来构造两个矩阵:
和.
现在我们不妨将两个矩阵相乘,化简过后可以得到:,也就是.
如果再将得到的新矩阵乘以,便可以得到。
也就是我们想得到第n项,就可以这么实现:,也就是。
看到幂我们就可以想到快速幂,所以最后程序的时间复杂度便是O(log n)。
代码
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;#define N 10
#define LL long longint n,mod;struct Matrix {LL n,m,c[N][N];Matrix() { memset(c,0,sizeof(c)); };void _read() {for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%lld",&c[i][j]);}Matrix operator * (const Matrix& a) {Matrix r;r.n=n;r.m=a.m;for(int i=1;i<=r.n;i++)for(int j=1;j<=r.m;j++)for(int k=1;k<=m;k++)r.c[i][j]= (r.c[i][j]+ (c[i][k] * a.c[k][j])%mod)%mod;return r;}void _print() {for(int i=1;i<=n;i++) {for(int j=1;j<=m;j++) {if(j!=1) cout<<" ";cout<<c[i][j];}if(i!=n) puts("");}}Matrix _power(int indexx) {Matrix tmp,sum;tmp._pre1();sum._pre1();while(indexx>0) {if(indexx&1) sum=sum*tmp;tmp=tmp*tmp;indexx/=2;}return sum;}void _pre1() {n=m=2;c[1][1]=0;c[1][2]=c[2][1]=c[2][2]=1;}void _pre2() {n=1,m=2;c[1][1]=c[1][2]=1;}}T,ans;int main() {cin>>n>>mod;ans._pre2();T._pre1();if(n<=2) { cout<<1; return 0; }T=T._power(n-3);ans=ans*T;cout<<ans.c[1][2];
}
那么前n项之和呢?
这里我们可以这么构造两个矩阵:(S(n)为前n项之和)
和将两个矩阵相乘,剩下的留给读者思考。
这里给出代码:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;#define N 10
#define LL long longint n,mod;struct Matrix {LL n,m,c[N][N];Matrix() { memset(c,0,sizeof(c)); };void _read() {for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%lld",&c[i][j]);}Matrix operator * (const Matrix& a) {Matrix r;r.n=n;r.m=a.m;for(int i=1;i<=r.n;i++)for(int j=1;j<=r.m;j++)for(int k=1;k<=m;k++)r.c[i][j]= (r.c[i][j]+ (c[i][k] * a.c[k][j])%mod)%mod;return r;}void _print() {for(int i=1;i<=n;i++) {for(int j=1;j<=m;j++) {if(j!=1) cout<<" ";cout<<c[i][j];}if(i!=n) puts("");}}Matrix _power(int indexx) {Matrix tmp,sum;tmp._pre1();sum._pre1();while(indexx>0) {if(indexx&1) sum=sum*tmp;tmp=tmp*tmp;indexx/=2;}return sum;}void _pre1() {n=m=3;c[3][2]=c[3][3]=c[2][3]=c[1][1]=c[2][1]=c[3][1]=1;}void _pre2() {n=1,m=3;c[1][1]=2;c[1][3]=c[1][2]=1;}}T,ans;int main() {cin>>n>>mod;if(n==2) return printf("%d",2%mod),0;if(n==1) return printf("%d",1%mod),0;ans._pre2();T._pre1();if(n<=2) { cout<<1; return 0; }T=T._power(n-3);ans=ans*T;cout<<ans.c[1][1];
}
浅谈矩阵加速——以时间复杂度为O(log n)的算法实现裴波那契数列第n项及前n之和使用矩阵加速法的优化求法相关推荐
- hdu 4549 M斐波那契数列(费马小定理 + 二分快速幂 + 矩阵快速幂)
M斐波那契数列 Time Limit: 3000/1 ...
- 2017.3.25 矩阵快速幂 求斐波那契数列第n项
对于矩阵快速幂只要知道矩阵取模.乘法原理就完全可以手推 口诀:行 列 被计算的行列的交点是结果对应的位置: 剩下的就是推矩阵: 其实根据矩阵的方程意义就很好推了: 码: #includ ...
- 浅谈斐波那契数列——从递推到矩阵乘法
说在前面 相信大家都已经知道这个中外著名的费波纳切数列了吧,关于费波那契数列有很多有趣的性质,但我们这里不讲,在这里我们只是利用斐波那契数列来引出另一个神奇的东西,矩阵乘法,递推在这里是起一个对比与铺 ...
- 斐波那契数列(二)--矩阵优化算法
之前写了一篇从斐波那契数列分析递归与动态规划(JAVA)来优化斐波那契数列,这样可以使算法的时间复杂度从O(n^2)变到O(n),这是使用递归公式f(n)=f(n-1)+f(n-2)求斐波那契数列的最 ...
- 奶牛家族(斐波那契数列的快速幂乘矩阵算法)
TX面试题: 已知有一头牛4年后开始生小牛,一次只能生一只,问20年后一共有多少头牛? 这种问题就是简单的递归: 这头奶牛在第四年后能不断生子直到第二十年,其子出生4年后又能不断生子-- 代码如下: ...
- 斐波那契数列和矩阵的特征值于特征向量的关系
从事软件开发的人对斐波那契数列可以说在熟悉不过了,一般是学习递归算法的入门案例写在教科书中,它用递推公式表达是这个样子的: 作为一名自尊自爱的码农,看到这个公式不免既心痒又难骚,必须要安排它一下,就拿 ...
- 动态规划法(一)从斐波那契数列谈起
动态规划法与分治方法 动态规划(Dynamic Programming)与分治方法相似,都是通过组合子问题的解来求解原问题.不同的是,分治方法通常将问题划分为互不相交的子问题,递归地求解子问题,再 ...
- python斐波那契数列前20项_兔子繁殖问题带来的智商碾压:斐波那契数列趣谈
本文来自公众号:超级数学建模 微信号 :supermodeling 原文标题:斐波那契数列趣谈 via 善科 by BB 一般认为斐波那契数列的提出是基于兔子的繁殖问题:如果一开始有一对兔子,它们每月 ...
- 菲波那切数列的时间复杂度分析-矩阵加速斐波那契数列计算
斐波那契数列 推荐一篇博文分享的时间复杂度分析 转载于:https://www.cnblogs.com/GarrettWale/p/11433241.html
最新文章
- 2017海克斯康拉斯维加斯美国大会 精彩即将开始
- 复合数值积分方法以及Python程序实现
- 跟着“路线图”,我们一起遨游机器学习的世界!
- 分享一个ASP.NET 文件压缩解压类 C#
- 初识Python之安装—anaconda pycharm区别
- 【数据结构与算法】之深入解析“UTF-8编码验证”的求解思路与算法示例
- qemu 规范路径_基于qemu-riscv64模拟器运行debian
- 某计算机公司的库存管理,《管理系统中计算机应用》应用题数据流程图汇总题及参考答案...
- 新来个专家吐槽我们:连qps都不懂,靠谱吗?
- 剑指offer(7)斐波那契数列
- 一. kafka 入门
- 企业微信api,企业微信sdk接口
- R - 简单随机抽样
- (纪中)2173. 无根树(tree)【SPFA】
- 魔兽TBC常用WA字符串收集
- 四色原型的学习心得分享
- 【机器学习基础】线性基函数模型
- 机器人“嘚瑟”怎么办?用加速度指令“hold”住它!
- 《嵌入式Linux系统开发:基于 Yocto Project》笔记
- 最新38道JVM面试题,看完读懂轻松收offer,进入大厂非常的easy