矩阵快速幂类似于快速幂,如果不懂快速幂的可以看一下我的这个博客:快速幂。
多了“矩阵”二字好像变得高大上,其实懂一点矩阵性质的人就觉得这好小儿科了。
先来说说矩阵的性质吧:
如图,一个m*n的矩阵A和m*n的矩阵B:
矩阵加法(这个可以忽略)
矩阵乘法(敲重点)
- A*B=C(一个m*n的矩阵)
以上中,矩阵快速幂有两个需要理解的,分别是矩阵乘法中的1和2.c
1显而易见,2.c是因为如: A的n次方 (A*A)*A*A*A*A........=(A)*(A*A)*(A*A*A*A)*(A*........而不影响。
思路由于和快速幂思路相同,所以直接代码(见矩阵快速幂模板题poj 3070 ):
f(n)=f(n-1)+f(n-2)等价于或
(这张盗的图)
需要的结构体:
struct matrix
{
ll m[3][3];
}ans;
m*n的矩阵A和m*n的矩阵B相乘:【这个函数可以重写,可以改成随便什么几乘以几*随便什么几乘以几的,这个得自己想想,因题而异】
matrix matrixmultiply(matrix a,matrix b,ll n)
{
matrix c;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
c.m[i][j]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
{
c.m[i][j]+=(a.m[i][k]*b.m[k][j])%mod;
}
return c;
}
矩阵快速幂主要函数实现(类快速幂的实现):
ll quickpow(matrix a,ll n)
{
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++)
{
if(i==j) ans.m[i][j]=1;
else ans.m[i][j]=0;
}
while(n)
{
if(n&1) ans=matrixmultiply(ans,a,2);
a=matrixmultiply(a,a,2);
n>>=1;
}
return ans.m[1][2];
}
主函数部分:
int main()
{
ll n;
while(cin>>n&&(n!=-1))
{
matrix a;
a.m[1][1]=a.m[1][2]=a.m[2][1]=1;
a.m[2][2]=0;
ll ans=0;
quickpow(a,n);
cout<<quickpow(a,n)%mod<<endl;;
}
return 0;
}
说一句大实话:上面的依旧是基础篇,也就是说,给好的矩阵让你算。这个矩阵——进阶让我们来感受一下表达式变矩阵来计算吧!
顺便解释一下这个图,其实左边那个是1*n的(也就是躺着一排的),最右边的也是一样的,否则无法进行矩阵乘法(看了半天 ╥﹏╥...),这样写可能只是为了好看吧。中间的状态转移矩阵每一行的各个系数讨到左边的矩阵中即可。
弄一个超好理解的图,乘号上面的那个矩阵就是每个变量,下面7*7的每行是对应的系数,等号右边对应每行的是每个得到的值,相对应而已。只是为了方便求中间那个状态转移矩阵(这样直接填7*7的矩阵就行)。
还有还有,推f(n-1)的也行,自行脑补。