矩阵快速幂 学习笔记
最近学习新知的速度是真的越来越快了,所以没有办法像以前那样慢慢写,就只好整合一下了。
由于时间关系,标准定义类的那些可以百度到的东西不多赘述,这里只谈自己的理解。
首先,我们需要了解矩阵。矩阵说白了就是一堆数,排成长方形的形状。
然后就是矩阵的运算,加减都很简单,这里谈一下乘法:
所以矩阵相乘,一定是有其中一个矩阵的行等于另一个矩阵的列的。
矩阵快速幂则和一般的快速幂的操作是一样的,只是把乘法变成了矩阵乘而已,就像重载那样。
这里还要说一下单位矩阵:
对于
n
∗
m
n*m
n∗m的矩阵,它的单位矩阵大小为
m
∗
m
m*m
m∗m,对于
m
∗
n
m*n
m∗n的矩阵,它的单位矩阵大小为
n
∗
n
n*n
n∗n。
也就是说单位矩阵都是正方形的,这是因为只有正方形的矩阵能保证结果和前一个矩阵形状相同。
单位矩阵的元素非0即1,从左上角到右下角的对角线上元素皆为1,其他皆为0。
单位矩阵的意义就是它相当于普通乘法里面的1,和任何数乘1都等于它本身那样,任何矩阵乘单位矩阵都等于原矩阵。
模板:
洛谷P3390
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 105
#define ll long long
#define MOD 1000000007
int n;
ll k;
struct node{
ll m[N][N];
};
node a,E/*单位矩阵*/;
node Mul(node x,node y)
{
node z;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
z.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++)
z.m[i][j]=(z.m[i][j]%MOD+x.m[i][k]*y.m[k][j]%MOD)%MOD;
return z;
}
node Pow(node x,ll y)
{
node ans=E;
while(y)
{
if(y&1)
ans=Mul(ans,x);
x=Mul(x,x);
y>>=1;
}
return ans;
}
int main()
{
scanf("%d %lld",&n,&k);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
scanf("%lld",&a.m[i][j]);
E.m[i][i]=1;
}
node ans=Pow(a,k);
for(int i=1;i<=n;i++)
{
for(int j=1;j<n;j++)
printf("%d ",ans.m[i][j]);
printf("%d\n",ans.m[i][n]);
}
}