矩阵

“我们的结合,拥有着我们的一部分”

矩阵

矩阵(Matrix)是指一个按照长方阵列排列的集合。一个由 $n$ 行 $m$ 列个数字排列的列表称为“ $m$ 行 $n$ 列”的矩阵,简称 $n*m$ 矩阵,记作:
$\begin{Bmatrix}
a_1&a_2&a_3&…&a_m\\
a_{m+1}&…&…&…&a_{2m}\\
…&…&…&…&…\\
a_{m(n-1)+1}&…&…&…&a_{nm}
\end{Bmatrix}$

矩阵加法/减法

令 $A,B$ 都是 $n*m$ 矩阵,则 $A+B=C$ ,满足:

$C=\begin{Bmatrix}
a_1+b_1&a_2+b_2&a_3+b_3&…&a_m+b_m\\
a_{m+1}+b_{m+1}&…&…&…&a_{2m}+b_{2m}\\
…&…&…&…&…\\
a_{m(n-1)+1}+b_{m(n-1)+1}&…&…&…&a_{nm}+b_{nm}
\end{Bmatrix}$

简单来说,即 $C_{i,j}=A_{i,j}+B_{i,j}$ ,减法同理。

矩阵乘法

$AB=C$ 满足 $C_{i,j}=\sum_{k=1}^{n}{A_{i,k}B_{k,j}}$

矩阵乘法能够实现,仅当 $A$ 的行数与 $B$ 的列数相等时。

举个栗子

$A=\begin{Bmatrix}1&2&3\\1&2&3\\\end{Bmatrix}$ , $B=\begin{Bmatrix}3&2\\1&3\\2&1\\\end{Bmatrix}$

那么对于 $C=A*B$ ,则

简单来讲就是

$C_{1,1}=\sum_{k=1}^{n=3}{A_{1,k}}*\sum_{k=1}^{m=3}{B_{k,1}}$

那么矩阵乘法的代码实现即是:

1
2
3
4
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
for(int k=1;k<=n;++k)
c[i][j]+=a[i][k]*b[k][j];

矩阵快速幂

对于一个矩阵 $G$ 来说, $G^k$ 中 $G_{i,j}$ 的含义为从 $i$ 走到 $j$ 步数为 $k$ 的方案数。

不用理解太多,就是用矩阵实现快速幂即可,将数乘换成矩阵乘法(蒟蒻改了一下午,才发现把 $i$ 打成了 $j$

LuoguP3390

AC Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<iomanip>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#define gh() getchar()
#define underMax(x,y) ((x)>(y)?(x):(y))
#define underMin(x,y) ((x)<(y)?(x):(y))
typedef long long ll;
using namespace std;
const ll p=1e9+7;
const int N=101;
template<class T>
inline void underRead(T &x)
{
x=0;
char ch=gh(),t=0;
while(ch<'0'||ch>'9') t|=ch=='-',ch=gh();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=gh();
if(t) x=-x;
}
ll n,k;
struct Matrix
{
ll m[N][N]; // 记得开long long
};
inline Matrix underCalc(Matrix a,Matrix b)
{
Matrix res;
memset(res.m,0,sizeof(res.m));
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
for(int l=1;l<=n;++l)
res.m[i][j]=(res.m[i][j]+(a.m[i][l]*b.m[l][j])%p)%p;
return res;
}
Matrix a;
inline void underExpr()
{
Matrix temp;
memset(temp.m,0,sizeof(temp.m));
for(int i=1;i<=n;++i) temp.m[i][i]=1;
while(k)
{
if(k&1) temp=underCalc(a,temp);
a=underCalc(a,a);
k>>=1;
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
printf("%lld ",temp.m[i][j]%p);
printf("\n");
}
}
int main()
{
// freopen("matrix.in","r",stdin);
// freopen("matrix.out","w",stdout);
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
scanf("%lld",&a.m[i][j]);
underExpr();
return 0;
}
/*
2 1
1 1
1 1
*/