0
点赞
收藏
分享

微信扫一扫

矩阵快速幂与斐波那契数列


矩阵快速幂与斐波那契数列

 

首先先说斐波那契数列,我们都知道它的递推式子是

n>=2 时f[n] = f[n-1]+f[n-2]

n = 1 时 f[1] = 1

n = 0 时 f[0] = 0

当题目让我们求一个斐波那契数列,比如n = 1000时,它变得非常大,所以通常题目会让我们求f[n]%mod。这样还能继续用递推做,但是……

当1<=n <= 1e9时,我们无法开这么大的数组,即使使用vector,o(n)的递推算法,也会让时间超限。那么,我们怎么从空间和时间上来求这么大的斐波那契数列呢?

 

首先你要具备线性代数中矩阵的有关知识~

矩阵的概念,性质,矩阵乘法等

 

知道矩阵乘法是怎么求得,那么代码怎么写呢?

比如有两个个矩阵A[m][t], B[t][n]  = C[m][n]  

代码:矩阵乘法

 

#include<bits/stdc++.h>
using namespace std;
struct mat
{
int a[15][15];
mat(){ //重载
memset(a,0,sizeof(a));
}
};
mat mul(mat x,mat y,int m,int n,int t)
{
mat res;
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
for(int k=0;k<t;k++)
{
res.a[i][j] += x.a[i][k]*y.a[k][j];
}
}
}
return res;
}
int main()
{
mat x,y;
int m = 2,n=2,t = 3; // 矩阵a[m][t]*b[t][n]
for(int i=0;i<m;i++)
{
for(int j=0;j<t;j++)
cin>>x.a[i][j];
}
for(int i=0;i<t;i++)
{
for(int j=0;j<n;j++)
cin>>y.a[i][j];
}
mat tmp = mul(x,y,m,n,t);
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
cout<<tmp.a[i][j]<<" ";
cout<<endl;
}
return 0;
}

那么对于矩阵乘法与递推式之间的关系:

如:斐波那契数列

n>=2 时f[n] = f[n-1]+f[n-2]

n = 1 时 f[1] = 1

n = 0 时 f[0] = 0

证明:

我们把几个递推式写成以下形式:

f[n+1] = 1 * f[n] + 1 * f[n-1];

f[n] = 1 * f[n] + 0 * f[n-1];

f[n] = 1 * f[n-1] + 1 * f[n-2];

f[n-1] = 1 * f[n-1] + 0 * f[n-2];

我们把上述表达式转换成矩阵乘法

  • 式:

矩阵快速幂与斐波那契数列_i++

 =

矩阵快速幂与斐波那契数列_i++_02

 X

矩阵快速幂与斐波那契数列_矩阵乘法_03

同理

  • 式:

矩阵快速幂与斐波那契数列_矩阵乘法_04

 =

矩阵快速幂与斐波那契数列_矩阵乘法_05

 X

矩阵快速幂与斐波那契数列_矩阵乘法_06

我们把②式带入①式

矩阵快速幂与斐波那契数列_矩阵乘法_07

  =

矩阵快速幂与斐波那契数列_斐波那契数列_08

X

矩阵快速幂与斐波那契数列_i++_09

 

 

 

我们发现右式子左边的幂p和右边矩阵左上角的f[]的下标s具有关系 p+s = n+1

如:上式的2和n-1, n-1+2 = n+1 所以我们能通过这个恒关系,推出

 

 

结论:

矩阵快速幂与斐波那契数列_i++_10

 =

矩阵快速幂与斐波那契数列_i++_11

X

矩阵快速幂与斐波那契数列_i++_12

                                           =

矩阵快速幂与斐波那契数列_矩阵乘法_13

  (注:f[1]=f[2] = 1, f[0] = 0)

 

哇~(ノ>ω<)ノ 我们发现通过求

矩阵快速幂与斐波那契数列_i++_14

这个矩阵的n次方,就可以知道f[n]啦!这里我就把推出来的

矩阵快速幂与斐波那契数列_斐波那契数列_15

 成为 基础矩阵 (个人习惯)

所以代码如下:d(d'∀')

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
const int M = 1e9+7;
typedef long long ll;
const int mod = 1e9+7;
int n ;
struct mat
{
ll a[15][15];
mat(){ //重载
memset(a,0,sizeof(a));
}
};
mat mul(mat x,mat y)
{
mat res;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
res.a[i][j] = (res.a[i][j]+x.a[i][k]*y.a[k][j])%mod;
return res;
}
ll qpow(int p)
{
mat bas;//基础矩阵
mat res;//单位矩阵
for(int i=0;i<2;i++)
res.a[i][i] = 1;
bas.a[0][0] = bas.a[0][1] = bas.a[1][0] = 1;
bas.a[1][1] = 0;
while(p)
{
if(1&p) res = mul(res,bas);
bas = mul(bas,bas);
p>>=1;
}
return res.a[0][1];//或者res.a[1][0]
}
int main()
{
cin>>n;
cout<<qpow(n)<<endl; //f[n] = qpow(n)
return 0;
}

 

 

 

举报

相关推荐

0 条评论