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

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. Linux--Linux的网络--05

    一层: HUB --- 集线器 总线型结构,使用泛洪方式 二层: 在早期,pc通信只需要MAC地址进行数据转发 网桥 --- 交换机  :维护MAC地址表 三层: 网络的增大,就需要逻辑地址(IP地址 ...

  2. hdu 5890 01背包 bitset

    注意不能每个T都mem 不然会T #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b, ...

  3. 1129. Recommendation System (25)

    Recommendation system predicts the preference that a user would give to an item. Now you are asked t ...

  4. 使用pycharm创建git项目的过程

    首先建立远程仓库,然后将远程仓库克隆到本地 然后在pycharm中以该目录创建项目(如果遇到说目录非空,不用管它,Location直接粘贴古来,不然找不到路径) 如果构建好项目说无效的SDK,那么选择 ...

  5. POJ 3741 Raid (平面最近点对)

    $ POJ~3741~Raid $ (平面最近点对) $ solution: $ 有两种点,现在求最近的平面点对.这是一道分治板子,但是当时还是想了很久,明明知道有最近平面点对,但还是觉得有点不对劲. ...

  6. git详细使用教程

    一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 二:SVN与Git的最主要的区别? SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以 ...

  7. codevs 2039 骑马修栅栏 USACO x

    题目描述 Description Farmer John每年有很多栅栏要修理.他总是骑着马穿过每一个栅栏并修复它破损的地方. John是一个与其他农民一样懒的人.他讨厌骑马,因此从来不两次经过一个栅栏 ...

  8. ubantu apt-get install安装php及开展

    .安装php apt-get install libapache2-mod-php5 php5 报错 E: Package 'libapache2-mod-php5' has no installat ...

  9. 6.20校内考试整理——大美江湖&&腐草为萤&&锦鲤抄题解

    先安利一下题目作者:一扶苏一 先看第一题: 这道题就是一道简单的模拟题,只要不管一开始的位置,模拟移动与格子对应的触发事件就行了.话不多说,看代码: #include<iostream> ...

  10. Android 拖拽功能的使用实例

    图片的拖拉功能是处理图片进一个有用且常用的功能,由于手机屏幕尺寸的限制,往往无法在手机上一次性的显示一张比较大的图片,也就是说,我们在手机上一次性只能看到图片的一部分,此时就可以使用图片的拖动功能来拖 ...