首先请连矩阵乘法乘法都还没有了解的同学简单看一下这篇博客:

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之和使用矩阵加速法的优化求法的更多相关文章

  1. [矩阵乘法]裴波拉契数列II

    [ 矩 阵 乘 法 ] 裴 波 拉 契 数 列 I I [矩阵乘法]裴波拉契数列II [矩阵乘法]裴波拉契数列II Description 形如 1 1 2 3 5 8 13 21 34 55 89 ...

  2. [矩阵乘法]裴波拉契数列III

    [ 矩 阵 乘 法 ] 裴 波 拉 契 数 列 I I I [矩阵乘法]裴波拉契数列III [矩阵乘法]裴波拉契数列III Description 求数列f[n]=f[n-1]+f[n-2]+1的第N ...

  3. 斐波那契数列第N项f(N)[矩阵快速幂]

    矩阵快速幂 定义矩阵A(m*n),B(p*q),A*B有意义当且仅当n=p.即A的列数等于B的行数. 且C=A*B,C(m*q). 例如: 进入正题,由于现在全国卷高考不考矩阵,也没多大了解.因为遇到 ...

  4. 51nod--1242 斐波那契数列第N项 (矩阵乘法优化)

    题目: 1242 斐波那契数列的第N项 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 斐波那契数列的定义如下: F(0) = 0 F(1) = 1 F(n) ...

  5. 斐波那契数列F(n)【n超大时的(矩阵加速运算) 模板】

    hihocoder #1143 : 骨牌覆盖问题·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题: 我们有一个 ...

  6. poj3070 求斐波那契数列第n项 ——矩阵快速幂

    题目:http://poj.org/problem?id=3070 用矩阵快速幂加速递推. 代码如下: #include<iostream> #include<cstdio> ...

  7. 【矩阵乘法】【快速幂】【递推】斐波那契数列&&矩乘优化递推模板

    题目大意: 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, ...

  8. HDU4549 M斐波那契数列 矩阵快速幂+欧拉函数+欧拉定理

    M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Sub ...

  9. HDU----(4549)M斐波那契数列(小费马引理+快速矩阵幂)

    M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Sub ...

随机推荐

  1. SPSS25 下载安装和激活

    目录 1. 其他版本 2. 安装步骤 3. 下载地址 1. 其他版本 参考:https://www.cnblogs.com/coco56/p/11648399.html 2. 安装步骤 打开安装包 下 ...

  2. Linux-day-1

    1. ls    作用:列出文件信息,默认为当前目录下 常用选项:         -a: 列出所有的文件,包括所有以.开头的隐藏文件         -d: 列出目录本身,并不包含目录中的文件    ...

  3. JS让函数只调用一次

    1 .  在第一次调用函数时,就将该函数内容腾空,以到达函数仅调用一次 ———————————————————————————————— 2 . 设置布尔值来控制后面的函数调用 window.onlo ...

  4. string初始化

    #include <iostream> using namespace std; int main(int argc, const char * argv[]) { //通过const c ...

  5. mybatis返回自增主键问题踩坑

    1 <insert id="insert" keyProperty="id" useGeneratedKeys="true"
 par ...

  6. 模块打包 webpack

    1.模块打包工具 2.工作方式: 1)将存在依赖关系的模块按照特定规则合并为单个JS文件,一次全部加载进页面中 2)在页面初始时加载一个入口模块,其他模块异步的进行加载 3.优势: 1)支持AMD,C ...

  7. spring security基本知识(三) 过滤详细说明

    在我们前面的文章Spring Security 初识(一)中,我们看到了一个最简单的 Spring Security 配置,会要求所有的请求都要经过认证.但是,这并不是我们想要的,我们通常想自定义应用 ...

  8. MSSQL时间格式转换

    sql server2000中使用convert来取得datetime数据类型样式(全) 日期数据格式的处理,两个示例: ), 时间一, ) 结果: :/*时间一般为getdate()函数或数据表里的 ...

  9. pyserial库-串口通讯模块

    pySerial 封装了串口通讯模块,支持Linux.Windows.BSD(可能支持所有支持POSIX的操作系统),支持Jython(Java)和IconPython(.NET and Mono). ...

  10. 花式赋值、列表、字典、解压缩、input()、格式化学习笔记

    目录 花式赋值 列表(list) 字典(dict) 解压缩 input()与用户交互 格式化的三种方式 f_String格式化(important) %s.%d占位符 format 格式化(不常用) ...