先来一段百科
矩阵乘法是一种高效的算法,可以把一些一维递推优化到log(n ),还可以求路径方案等,所以更是一种应用性极强的算法。矩阵,是线性代数中的基本概念之一。一个m×n的矩阵就是m×n个数排成m行n列的一个数阵。由于它把许多数据紧凑的集中到了一起,所以有时候可以简便地表示一些复杂的模型。矩阵乘法看起来很奇怪,但实际上非常有用,应用也十分广泛。一个矩阵说穿了就是一个二维数组。一个n行m列的矩阵可以乘以一个m行p列的矩阵,得到的结果是一个n行p列的矩阵,其中的第i行第j列位置上的数等于前一个矩阵第i行上的m个数与后一个矩阵第j列上的m个数对应相乘后所有m个乘积的和。 ——by 互动百科
怎么说呢,反正这个东西可以加快某些算法或者运算的速度
一般配合矩阵快速幂使用
关于如何相乘,其实上面的百科说的已经很清楚了
具体实现如下:
inline juzhen cheng(juzhen a,juzhen b){
memset(z.a,0,sizeof z.a);
for(ll i=1;i<=2;i++)
for(ll j=1;j<=2;j++)
for(ll k=1;k<=2;k++)z.a[i][j]=(z.a[i][j]+a.a[i][k]*b.a[k][j])%MOD;
return z;
}
矩阵乘法在运算时要注意以下几个基本性质
1.结合性 ( AB) C= A( BC).
2.对加法的分配性 ( A+ B) C= AC+ BC, C( A+ B)= CA+ CB .
3.对数乘的结合性 k( AB)=( kA) B = A( kB).
4.关于转置 (AB)’=B’A’.
所以矩阵乘法好像不支持交换律,这个要注意啊
其实矩阵乘法很简单,只是对应乘一下
真正难点在于如何建出这个矩阵
这个嘛要看具体题目了
比如下面一道例题:
Luogu1962 斐波那契数列
https://www.luogu.org/problem/show?pid=1962
题目要求 f(n) mod 1000000007 的值
我们总不可能一直这么一个一个推下去吧。。。
如果我们构造这样一个矩阵
通过斐波那契和矩乘性质,我们可以构造出这样一个矩阵式子
对吧,自己推一下就能知道的吧
所以我们就可以放心地求出第n项啦,时间O(log n)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll MOD=1000000007;
struct juzhen{
ll a[3][3];
}x,y,z;
inline juzhen cheng(juzhen a,juzhen b){
memset(z.a,0,sizeof z.a);
for(ll i=1;i<=2;i++)
for(ll j=1;j<=2;j++)
for(ll k=1;k<=2;k++)z.a[i][j]=(z.a[i][j]+a.a[i][k]*b.a[k][j])%MOD;
return z;
}
inline ll mi(ll n){
x.a[1][1]=x.a[1][2]=x.a[2][1]=y.a[1][1]=y.a[1][2]=y.a[2][1]=1;
while(n!=0){
if(n&1==1)x=cheng(x,y);
y=cheng(y,y);n=n>>1;
}
return x.a[2][2]%MOD;
}
int main()
{
ll n;scanf("%lld",&n);
printf("%lld",mi(n));
return 0;
}
更多矩乘题目我会更新的啦
敬请期待