矩阵在计算机数学中有比较重要的内容,它可以优化很多推论,在这里我们将简单介绍一下。
由 n × m n\times m n×m个数 a i j ( i = 1 , 2 , … , n , j = 1 , 2 , … , m ) a_{ij}(i=1,2,\dots,n,j=1,2,\dots,m) aij(i=1,2,…,n,j=1,2,…,m)排成的 m m m行 n n n列的数表(是一组数)。通用形式:
[ a 1 a 2 ⋯ ⋯ a n b 1 b 2 ⋯ ⋯ b n ⋯ ⋯ ⋯ ⋯ ⋯ z 1 z 2 ⋯ ⋯ z n ] \left[ \begin{matrix} a_1 & a_2 & \cdots\cdots & a_n\\ b_1 & b_2 & \cdots\cdots & b_n\\ \cdots & \cdots & \cdots\cdots & \cdots\\ z_1 & z_2 & \cdots\cdots & z_n \end{matrix} \right] a1b1⋯z1a2b2⋯z2⋯⋯⋯⋯⋯⋯⋯⋯anbn⋯zn
下面了解一些特殊的矩阵:
两个矩阵进行一般的加法运算的前提是这两个矩阵为同型矩阵,我们只需要将对应位置的元素相加即可。
A = [ a 1 a 2 a 3 b 1 b 2 b 3 c 1 c 2 c 3 ] , B = [ d 1 d 2 d 3 e 1 e 2 e 3 f 1 f 2 f 3 ] , A + B = [ a 1 + d 1 a 2 + d 2 a 3 + d 3 b 1 + e 1 b 2 + e 2 b 3 + e 3 c 1 + f 1 c 2 + f 2 c 3 + f 3 ] A=\left[ \begin{matrix} a_1 & a_2 & a_3\\ b_1 & b_2 & b_3\\ c_1 & c_2 & c_3 \end{matrix} \right] ,B=\left[ \begin{matrix} d_1 & d_2 & d_3\\ e_1 & e_2 & e_3\\ f_1 & f_2 & f_3 \end{matrix} \right] ,A+B=\left[ \begin{matrix} a_1+d_1 & a_2+d_2 & a_3+d_3\\ b_1+e_1 & b_2+e_2 & b_3+e_3\\ c_1+f_1 & c_2+f_2 & c_3+f_3 \end{matrix} \right] A= a1b1c1a2b2c2a3b3c3 ,B= d1e1f1d2e2f2d3e3f3 ,A+B= a1+d1b1+e1c1+f1a2+d2b2+e2c2+f2a3+d3b3+e3c3+f3
在矩阵的加法运算中,满足交换律和结合律,也就是 A + B = B + A , ( A + B ) + C = A + ( B + C ) A+B=B+A,(A+B)+C=A+(B+C) A+B=B+A,(A+B)+C=A+(B+C)。
在实数运算中,减法为加法的逆运算,同样的,在矩阵运算中也是如此。
A = [ a 1 a 2 a 3 b 1 b 2 b 3 c 1 c 2 c 3 ] , B = [ d 1 d 2 d 3 e 1 e 2 e 3 f 1 f 2 f 3 ] , A − B = [ a 1 − d 1 a 2 − d 2 a 3 − d 3 b 1 − e 1 b 2 − e 2 b 3 − e 3 c 1 − f 1 c 2 − f 2 c 3 − f 3 ] A=\left[ \begin{matrix} a_1 & a_2 & a_3\\ b_1 & b_2 & b_3\\ c_1 & c_2 & c_3 \end{matrix} \right] ,B=\left[ \begin{matrix} d_1 & d_2 & d_3\\ e_1 & e_2 & e_3\\ f_1 & f_2 & f_3 \end{matrix} \right] ,A-B=\left[ \begin{matrix} a_1-d_1 & a_2-d_2 & a_3-d_3\\ b_1-e_1 & b_2-e_2 & b_3-e_3\\ c_1-f_1 & c_2-f_2 & c_3-f_3 \end{matrix} \right] A= a1b1c1a2b2c2a3b3c3 ,B= d1e1f1d2e2f2d3e3f3 ,A−B= a1−d1b1−e1c1−f1a2−d2b2−e2c2−f2a3−d3b3−e3c3−f3
在数乘运算中,我们类比向量来进行理解,在数乘向量运算中,只需要将向量中的每个元素乘上那个数就可以了,数乘矩阵也是如此。
A = [ a 1 a 2 a 3 b 1 b 2 b 3 c 1 c 2 c 3 ] , 3 × A = [ 3 × a 1 3 × a 2 3 × a 3 3 × b 1 3 × b 2 3 × b 3 3 × c 1 3 × c 2 3 × c 3 ] A=\left[ \begin{matrix} a_1 & a_2 & a_3\\ b_1 & b_2 & b_3\\ c_1 & c_2 & c_3 \end{matrix} \right] ,3\times A=\left[ \begin{matrix} 3\times a_1 & 3\times a_2 & 3\times a_3\\ 3\times b_1 & 3\times b_2 & 3\times b_3\\ 3\times c_1 & 3\times c_2 & 3\times c_3 \end{matrix} \right] A= a1b1c1a2b2c2a3b3c3 ,3×A= 3×a13×b13×c13×a23×b23×c23×a33×b33×c3
数乘矩阵运算中,满足如下运算律: ( λ × μ ) × A = λ × ( μ × A ) , ( λ + μ ) × A = λ × A + μ × A , λ ( A + B ) = λ × A + λ × B (\lambda\times\mu)\times A=\lambda\times(\mu\times A),(\lambda+\mu)\times A=\lambda\times A+\mu\times A,\lambda(A+B)=\lambda\times A+\lambda\times B (λ×μ)×A=λ×(μ×A),(λ+μ)×A=λ×A+μ×A,λ(A+B)=λ×A+λ×B。
了解完矩阵,你们现在我们来看看什么是矩阵乘法?
再次先说明:矩阵相乘前一个矩阵的列数必须等于后一个矩阵的行数 A m × s × B s × n A_{m\times s}\times B_{s\times n} Am×s×Bs×n,乘积矩阵的函数为前一个矩阵的行数,列数为后一个矩阵的列数 C m × n C_{m\times n} Cm×n。
现在我们设 C = A × B C=A\times B C=A×B(三个都是矩阵),那么就有 C [ i ] [ j ] = ∑ i = 1 s ( A [ i ] [ k ] × B [ k ] [ j ] ) C[i][j]=\sum_{i=1}^s(A[i][k]\times B[k][j]) C[i][j]=∑i=1s(A[i][k]×B[k][j])。通俗的说,结果矩阵的第 i i i行第 j j j列等于矩阵 A A A第 i i i行与矩阵 B B B第 j j j列分别乘积的和(现在明白为什么矩阵乘法要求 A A A的行数与 B B B的列数相同了吧,因为要保证有数相乘,若不相等会导致缺少一些项)
在普通的乘法中,一个数乘 1 1 1还是等于它本身,在矩阵乘法中也有这么一个 “ 1 ” “1” “1”,它就是单位矩阵。不同于普通乘法中的单位 1 1 1,对于不同矩阵他们的单位矩阵大小是不同的对于 n × m n\times m n×m的矩阵,它的单位矩阵大小为 m × m m\times m m×m,对于 m × n m\times n m×n的矩阵,它的单位矩阵大小为 n × n n\times n n×n。也就是说单位矩阵都是正方形的,这是因为只有正方形的矩阵能保证结果和前一个矩阵形状相同,单位矩阵的元素非 0 0 0即 1 1 1,从左上角到右下角的对角线上元素皆为 1 1 1,其他皆为 0 0 0。
了解了这么多,我们现在来看矩阵快速幂,矩阵快速幂就是将矩阵和快速幂相结合,由于矩阵乘法满足结合律,所以我们只需要把它按照一般的快速幂来写即可。
int n, m, p, k;
struct Mat{
int arr[10][10];
};
Mat Add(Mat x, Mat y){
Mat temp;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
temp.arr[i][j] = x.arr[i][j] + y.arr[i][j];
}
}
return temp;
}
Mat Sub(Mat x, Mat y){
Mat temp;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
temp.arr[i][j] = x.arr[i][j] - y.arr[i][j];
}
}
return temp;
}
Mat Mul(Mat x, Mat y){
Mat temp;
memset(temp.arr,0,sizeof(temp.arr));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
for (int k = 1; k <= p; k++) {
temp.arr[i][j] = temp.arr[i][j] + x.arr[i][k] * y.arr[k][j];
}
}
}
return temp;
}
int main(){
Mat res, a;
cin >> n >> k;
m = n;
p = n;
for(int i = 1; i <= n; i++){
res.arr[i][i] = 1;
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
cin >> a.arr[i][j];
}
}
while(k){
if(k & 1) res = Mul(res,a);
a = Mul(a,a);
k >>= 1;
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
cout << res.arr[i][j] << " ";
}
cout << endl;
}
return 0;
}