矩阵
定义
顾名思义。就是由元素组成的矩形阵列。
表示
一个 n n n行 m m m列的矩形阵列即是 n n n行 m m m列的矩阵,例如 2 2 2行 3 3 3列的矩阵: ( a b c d e f ) \begin{pmatrix}a&b&c\\d&e&f\end{pmatrix} (adbecf) 在C++程序中可以使用二维数组表示矩阵。
struct Matrix
{
int d[2][3];
};
零矩阵
所有元素都为数0的矩阵称为零矩阵。
n阶方阵
n n n行 n n n列的矩阵称为 n n n阶方阵 。
上三角矩阵
主对角线:n阶方阵的左上角与右下角之间的连线称为它的主对角线。
n
n
n阶方阵的主对角线下方的元素全为零的方阵称为上三角矩阵。
下三角矩阵
n n n阶方阵的主对角线上方的元素全为零的方阵称为下三角矩阵。
单位元矩阵
单位元矩阵:n阶方阵的主对角线上的值全是1,非主对角线上的值全是0。例如:3阶方阵
(
1
0
0
0
1
0
0
0
1
)
\begin{pmatrix}1&0&0\\0&1&0\\0&0&1\end{pmatrix}
⎝⎛100010001⎠⎞
单位元矩阵与任何矩阵相乘都等于原矩阵。
任何矩阵和单位元矩阵相乘都等于原矩阵。(两条不同)
邻接矩阵
例题:各城市之间交通连接形成一个交通网络图。设图上有
n
n
n个城市构成的节(顶)点
v
1
v_1
v1、
v
2
v_2
v2、···、
v
n
v_n
vn,在每两个节点(城市)之间以线段相连接,这些线段可以是有向的,用箭头表示;也可以是无向的,因而可画出双箭头。这就形成了一个交通网络图,这样的图称为有向图(如果图上线段都是双向的,可以不画箭头,称为无向图),这个图可以用
n
×
n
n×n
n×n矩阵表示,这个矩阵叫做邻接矩阵,它的行和列分别表示这些节点的编号,行号表示出发节点(出度),列号表示到达节点(入度)。任何一条有向线段,在矩阵中用一个数值为1的元素表示,即若邻接矩阵
A
=
(
a
i
j
)
n
×
n
A=(a_{ij})_{n×n}
A=(aij)n×n,则
a
i
j
=
{
1
,
节
点
v
i
到
v
j
有
箭
头
(
不
含
中
间
节
点
)
0
,
节
点
v
i
到
v
j
没
有
箭
头
a_{ij} = \begin{cases}1,节点v_i到v_j有箭头(不含中间节点)\\0,节点v_i到v_j没有箭头\end{cases}
aij={1,节点vi到vj有箭头(不含中间节点)0,节点vi到vj没有箭头
例如图:
邻接矩阵:
v
1
v
2
v
3
v
4
v
5
v
1
0
1
0
0
0
v
2
0
0
1
0
0
v
3
0
1
0
1
1
v
4
1
0
0
0
0
v
5
1
1
0
1
0
\begin{matrix}&v_1&v_2&v_3&v_4&v_5\\v_1&0&1&0&0&0\\v_2&0&0&1&0&0\\v_3&0&1&0&1&1\\v_4&1&0&0&0&0\\v_5&1&1&0&1&0\end{matrix}
v1v2v3v4v5v100011v210101v301000v400101v500100
矩阵的运算
加法
矩阵加法首先满足两个矩阵的行和列一样,即都是
n
n
n行
m
m
m列的矩阵,相加结果也是
n
n
n行
m
m
m列的矩阵,即:
A
(
i
,
j
)
+
B
(
i
,
j
)
=
(
A
+
B
)
(
i
,
j
)
A(i,j)+B(i,j)=(A+B)(i,j)
A(i,j)+B(i,j)=(A+B)(i,j)。
(
1
3
1
1
0
0
)
+
(
0
0
5
7
5
0
)
=
(
1
+
0
3
+
0
1
+
5
1
+
7
0
+
5
0
+
0
)
=
(
1
3
6
8
5
0
)
\begin{pmatrix}1&3&1\\1&0&0\end{pmatrix}+\begin{pmatrix}0&0&5\\7&5&0\end{pmatrix} = \begin{pmatrix}1+0&3+0&1+5\\1+7&0+5&0+0\end{pmatrix}=\begin{pmatrix}1&3&6\\8&5&0\end{pmatrix}
(113010)+(070550)=(1+01+73+00+51+50+0)=(183560)
运算规则
- 满足交换律
A + B = B + A A+B=B+A A+B=B+A - 满足结合律
( A + B ) + C = A + ( B + C ) (A+B)+C=A+(B+C) (A+B)+C=A+(B+C)
减法
矩阵减法首先满足两个矩阵的行和列一样,即都是
n
n
n行
m
m
m列的矩阵,相减结果也是
n
n
n行
m
m
m列的矩阵,即:
A
(
i
,
j
)
−
B
(
i
,
j
)
=
(
A
−
B
)
(
i
,
j
)
A(i,j)-B(i,j)=(A-B)(i,j)
A(i,j)−B(i,j)=(A−B)(i,j)。
(
1
3
1
1
0
0
)
+
(
0
0
5
7
5
0
)
=
(
1
−
0
3
−
0
1
−
5
1
−
7
0
−
5
0
−
0
)
=
(
1
3
−
4
−
6
−
5
0
)
\begin{pmatrix}1&3&1\\1&0&0\end{pmatrix}+\begin{pmatrix}0&0&5\\7&5&0\end{pmatrix} = \begin{pmatrix}1-0&3-0&1-5\\1-7&0-5&0-0\end{pmatrix}=\begin{pmatrix}1&3&-4\\-6&-5&0\end{pmatrix}
(113010)+(070550)=(1−01−73−00−51−50−0)=(1−63−5−40)
运算规则
- 满足交换律
A + B = B + A A+B=B+A A+B=B+A - 满足结合律
( A + B ) + C = A + ( B + C ) (A+B)+C=A+(B+C) (A+B)+C=A+(B+C)
数乘
注意这里不是乘法,只是数乘,用一个数,去乘矩阵里的每一个数。
λ
A
(
i
,
j
)
=
λ
A
i
j
λA(i,j)=λA_{ij}
λA(i,j)=λAij
5
∗
(
1
3
1
1
0
0
)
=
(
5
∗
1
5
∗
3
5
∗
1
5
∗
1
5
∗
0
5
∗
0
)
=
(
5
15
5
5
0
0
)
5*\begin{pmatrix}1&3&1\\1&0&0\end{pmatrix}= \begin{pmatrix}5*1&5*3&5*1\\5*1&5*0&5*0\end{pmatrix}=\begin{pmatrix}5&15&5\\5&0&0\end{pmatrix}
5∗(113010)=(5∗15∗15∗35∗05∗15∗0)=(5515050)
运算规则
- 满足结合律
( λ μ ) A = λ ( μ A ) (λμ)A=λ(μA) (λμ)A=λ(μA)
( λ + μ ) A = λ A + μ A (λ+μ)A=λA+μA (λ+μ)A=λA+μA - 满足分配律
λ ( A + B ) = λ A + λ B λ(A+B)=λA+λB λ(A+B)=λA+λB
乘法
这个才是矩阵的重头戏。矩阵乘法中,两矩阵必须满足矩阵
A
(
n
a
,
m
a
)
A(n_a,m_a)
A(na,ma)的列等于矩阵
B
(
n
b
,
m
b
)
B(n_b,m_b)
B(nb,mb)的行。即
m
a
=
n
b
m_a=n_b
ma=nb。相乘的结果矩阵
C
(
n
c
,
m
c
)
C(n_c,m_c)
C(nc,mc)中的行等于矩阵
A
(
n
a
,
m
a
)
A(n_a,m_a)
A(na,ma)中的行,即
n
c
=
n
a
n_c=n_a
nc=na,矩阵
C
(
n
c
,
m
c
)
C(n_c,m_c)
C(nc,mc)中的列等于矩阵
B
(
n
b
,
m
b
)
B(n_b,m_b)
B(nb,mb)中的列,即
m
c
=
m
b
m_c=m_b
mc=mb。
矩阵乘法的公式:
C
(
i
,
j
)
=
A
(
i
,
1
)
∗
B
(
1
,
j
)
+
A
(
i
,
2
)
∗
B
(
2
,
j
)
+
⋅
⋅
⋅
+
A
(
i
,
m
a
)
∗
B
(
n
b
,
j
)
=
∑
k
=
1
m
a
A
(
i
,
k
)
∗
B
(
k
,
j
)
C(i,j) = A(i,1)*B(1,j)+A(i,2)*B(2,j)+···+A(i,m_a)*B(n_b,j) =\sum_{k=1}^{m_a}{A(i,k)*B(k,j)}
C(i,j)=A(i,1)∗B(1,j)+A(i,2)∗B(2,j)+⋅⋅⋅+A(i,ma)∗B(nb,j)=∑k=1maA(i,k)∗B(k,j)
(
1
0
2
−
1
3
1
)
∗
(
3
1
2
1
1
0
)
=
(
(
1
∗
3
+
0
∗
2
+
2
∗
1
)
(
1
∗
1
+
0
∗
1
+
2
∗
0
)
(
−
1
∗
3
+
3
∗
2
+
1
∗
1
)
(
−
1
∗
1
+
3
∗
1
+
1
∗
0
)
)
=
(
5
1
4
2
)
\begin{pmatrix}1&0&2\\-1&3&1\end{pmatrix}*\begin{pmatrix}3&1\\2&1\\1&0\end{pmatrix} = \begin{pmatrix}(1*3+0*2+2*1)&(1*1+0*1+2*0)\\(-1*3+3*2+1*1)&(-1*1+3*1+1*0)\end{pmatrix}=\begin{pmatrix}5&1\\4&2\end{pmatrix}
(1−10321)∗⎝⎛321110⎠⎞=((1∗3+0∗2+2∗1)(−1∗3+3∗2+1∗1)(1∗1+0∗1+2∗0)(−1∗1+3∗1+1∗0))=(5412)
运算规则
- 满足结合律
( A B ) C = A ( B C ) (AB)C=A(BC) (AB)C=A(BC)
( λ A ) B = λ ( A B ) + A ( λ B ) (λA)B=λ(AB)+A(λB) (λA)B=λ(AB)+A(λB) - 满足分配律
A ( B ± C ) = A B ± A C A(B±C)=AB±AC A(B±C)=AB±AC(左分配律)
( B ± C ) A = B A ± C A (B±C)A=BA±CA (B±C)A=BA±CA(右分配律)
参考链接:http://www2.edu-edu.com.cn/lesson_crs78/self/j_0022/soft/ch0605.html
矩阵快速幂
我们已经学习过数字快速幂,例如:
A
k
%
m
o
d
A^k\%mod
Ak%mod。
数字快速幂代码:
typedef long long LL;//为long long重命名
LL ppow(LL n, LL k)
{
LL res = n;
LL ans = 1;
while(k)
{
if(k&1) ans = ans*res;
res = res*res;
k >>= 1;
}
return ans;
}
矩阵快速幂和数字快速幂大致相同,只需要将 a n s 、 r e s ans、res ans、res两个 L L LL LL类型的整数改成矩阵就可以了。
const int m_max = 15;
struct Matrix
{
int d[m_max][m_max];
};
int m_size;
Matrix matrix_mul(Matrix a, Matrix b)
{
Matrix ans;
for(int i = 0; i < m_size; i++)
for(int j = 0; j < m_size; j++)
{
ans.d[i][j] = 0;
for(int k = 0; k < m_size; k++)
{
ans.d[i][j] += (a.d[i][k]*b.d[k][j]);
}
}
return ans;
}
Matrix init()//把矩阵初始化单位元矩阵
{
Matrix ans;
for(int i = 0; i < m_size; i++)
for(int j = 0; j < m_size; j++)
ans.d[i][j] = i==j?1:0;
return ans;
}
Matrix ppow(Matrix a,int k)
{
Matrix ans = init();
Matrix res = a;
while(k)
{
if(k&1)
ans = matrix_mul(ans, res);
res = matrix_mul(res, res);
k >>= 1;
}
return ans;
}
第二十四天训练学习A题解
题目链接:A:Tr A
题解:板子题,题意很明确。
代码:
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cmath>
using namespace std;
const int mod = 200907;
typedef long long LL;
const int m_max = 15;
struct Matrix
{
int d[m_max][m_max];
};
int m_size;
Matrix matrix_mul(Matrix a, Matrix b)
{
Matrix ans;
for(int i = 0; i < m_size; i++)
for(int j = 0; j < m_size; j++)
{
ans.d[i][j] = 0;
for(int k = 0; k < m_size; k++)
{
ans.d[i][j] = (ans.d[i][j]+a.d[i][k]*b.d[k][j])%9973;
}
}
return ans;
}
Matrix init()//把矩阵初始化单位元矩阵
{
Matrix ans;
for(int i = 0; i < m_size; i++)
for(int j = 0; j < m_size; j++)
ans.d[i][j] = i==j?1:0;
return ans;
}
Matrix ppow(Matrix a,int k)
{
Matrix ans = init();
Matrix res = a;
while(k)
{
if(k&1)
ans = matrix_mul(ans, res);
res = matrix_mul(res, res);
k >>= 1;
}
return ans;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int k;
Matrix a;
scanf("%d%d", &m_size, &k);
for(int i = 0; i < m_size; i++)
{
for(int j = 0; j < m_size; j++)
{
scanf("%d", &a.d[i][j]);
}
}
Matrix ans = ppow(a,k);
int sum = 0;
for(int i = 0; i < m_size; i++)
{
sum += ans.d[i][i];
}
printf("%d\n", sum%9973);
}
return 0;
}