浅谈矩阵加速——以时间复杂度为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 long
int 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 long
int 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之和使用矩阵加速法的优化求法的更多相关文章
- [矩阵乘法]裴波拉契数列II
[ 矩 阵 乘 法 ] 裴 波 拉 契 数 列 I I [矩阵乘法]裴波拉契数列II [矩阵乘法]裴波拉契数列II Description 形如 1 1 2 3 5 8 13 21 34 55 89 ...
- [矩阵乘法]裴波拉契数列III
[ 矩 阵 乘 法 ] 裴 波 拉 契 数 列 I I I [矩阵乘法]裴波拉契数列III [矩阵乘法]裴波拉契数列III Description 求数列f[n]=f[n-1]+f[n-2]+1的第N ...
- 斐波那契数列第N项f(N)[矩阵快速幂]
矩阵快速幂 定义矩阵A(m*n),B(p*q),A*B有意义当且仅当n=p.即A的列数等于B的行数. 且C=A*B,C(m*q). 例如: 进入正题,由于现在全国卷高考不考矩阵,也没多大了解.因为遇到 ...
- 51nod--1242 斐波那契数列第N项 (矩阵乘法优化)
题目: 1242 斐波那契数列的第N项 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 斐波那契数列的定义如下: F(0) = 0 F(1) = 1 F(n) ...
- 斐波那契数列F(n)【n超大时的(矩阵加速运算) 模板】
hihocoder #1143 : 骨牌覆盖问题·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题: 我们有一个 ...
- poj3070 求斐波那契数列第n项 ——矩阵快速幂
题目:http://poj.org/problem?id=3070 用矩阵快速幂加速递推. 代码如下: #include<iostream> #include<cstdio> ...
- 【矩阵乘法】【快速幂】【递推】斐波那契数列&&矩乘优化递推模板
题目大意: F[0]=0 F[1]=1 F[n+2]=F[n+1]+F[n] 求F[n] mod 104. F[n+2] F[n+1] = 1 1 1 0 * F[n+1] F[n] 记这个矩阵为A, ...
- HDU4549 M斐波那契数列 矩阵快速幂+欧拉函数+欧拉定理
M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Sub ...
- HDU----(4549)M斐波那契数列(小费马引理+快速矩阵幂)
M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Sub ...
随机推荐
- MySQL事务提交与回滚
提交 为了演示效果,需要打开两个终端窗口,使用同一个数据库,操作同一张表 step1:连接 终端1:查询商品分类信息 select * from goods_cates; step2:增加数据 终端2 ...
- 判断是否是iframe框架打开登录页, iframe框架着顶部页面刷新
if (window != top) top.location.href = location.href;
- if [ $? -eq 0 ]; then该语句是什么含义?
某个shell脚本 # mkimage.sh echo "make and copy android images" ./mkimage.sh ]; then echo " ...
- Linux之bash的变量
1. 变量的显示,echo echo $变量 或 echo ${变量} eg. echo $HOME 或 echo ${HOME} 2. 变量的设置 变量的设置规则: (1)变量与变 ...
- vue-router解析,vue-router原理解析
前言:新一季面试季,重新整理一些知识点: 本文详细说明自己对vue-router原理的理解: 参考: 源码:vuejs/vue-router v2.2.1 - github 文档:vue-router ...
- 使用Vscode添加中文汉化插件
一.首先打开Vscode,找到该软件的扩展,如下: 二.点击扩展按钮之后,会出现如下的界面,有一个扩展搜索输入框,输入chinese之后,会随之产生一些匹配的插件 三.重启一下Vscode,然后就看到 ...
- 绑定class -vue
1.值为对象 :class = "{ 'text-red': isActive }" data () { return { isActive : true } } :class = ...
- spring security基本知识(三) 过滤详细说明
在我们前面的文章Spring Security 初识(一)中,我们看到了一个最简单的 Spring Security 配置,会要求所有的请求都要经过认证.但是,这并不是我们想要的,我们通常想自定义应用 ...
- tensorflow打印pb、ckpt模型的参数以及在tensorboard里显示图结构
打印pb模型参数及可视化结构import tensorflow as tf from tensorflow.python.framework import graph_util tf.reset_de ...
- 【转载】 原生js判断某个元素是否滚动到底部
document.querySelector('.content').addEventListener('scroll',function () { //读取内容区域的真实高度(滚动条高) // co ...