ACM矩阵基础入门

矩阵

定义

  顾名思义。就是由元素组成的矩形阵列。

表示

  一个 n n m m 列的矩形阵列即是 n n m m 列的矩阵,例如 2 2 3 3 列的矩阵: ( a b c d e f ) \begin{pmatrix}a&b&c\\d&e&f\end{pmatrix} 在C++程序中可以使用二维数组表示矩阵。

struct Matrix
{
    int d[2][3];
};

零矩阵

  所有元素都为数0的矩阵称为零矩阵

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}
单位元矩阵与任何矩阵相乘都等于原矩阵。
任何矩阵和单位元矩阵相乘都等于原矩阵。(两条不同)

邻接矩阵

  例题:各城市之间交通连接形成一个交通网络图。设图上有 n n 个城市构成的节(顶)点 v 1 v_1 v 2 v_2 、···、 v n v_n ,在每两个节点(城市)之间以线段相连接,这些线段可以是有向的,用箭头表示;也可以是无向的,因而可画出双箭头。这就形成了一个交通网络图,这样的图称为有向图(如果图上线段都是双向的,可以不画箭头,称为无向图),这个图可以用 n × n n×n 矩阵表示,这个矩阵叫做邻接矩阵,它的行和列分别表示这些节点的编号,行号表示出发节点(出度),列号表示到达节点(入度)。任何一条有向线段,在矩阵中用一个数值为1的元素表示,即若邻接矩阵 A = ( a i j ) n × n A=(a_{ij})_{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}
例如图:在这里插入图片描述
邻接矩阵: 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}

矩阵的运算

加法

  矩阵加法首先满足两个矩阵的行和列一样,即都是 n n m m 列的矩阵,相加结果也是 n n m m 列的矩阵,即: 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}

运算规则

  1. 满足交换律
    A + B = B + A A+B=B+A
  2. 满足结合律
    ( A + B ) + C = A + ( B + C ) (A+B)+C=A+(B+C)

减法

  矩阵减法首先满足两个矩阵的行和列一样,即都是 n n m m 列的矩阵,相减结果也是 n n m m 列的矩阵,即: 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}

运算规则

  1. 满足交换律
    A + B = B + A A+B=B+A
  2. 满足结合律
    ( A + B ) + C = A + ( B + C ) (A+B)+C=A+(B+C)

数乘

  注意这里不是乘法,只是数乘,用一个数,去乘矩阵里的每一个数。 λ A ( i , j ) = λ A i j λA(i,j)=λA_{ij}
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}

运算规则

  1. 满足结合律
    ( λ μ ) A = λ ( μ A ) (λμ)A=λ(μA)
    ( λ + μ ) A = λ A + μ A (λ+μ)A=λA+μA
  2. 满足分配律
    λ ( A + B ) = λ A + λ B λ(A+B)=λA+λB

乘法

  这个才是矩阵的重头戏。矩阵乘法中,两矩阵必须满足矩阵 A ( n a , m a ) A(n_a,m_a) 的列等于矩阵 B ( n b , m b ) B(n_b,m_b) 的行。即 m a = n b m_a=n_b 。相乘的结果矩阵 C ( n c , m c ) C(n_c,m_c) 中的行等于矩阵 A ( n a , m a ) A(n_a,m_a) 中的行,即 n c = n a n_c=n_a ,矩阵 C ( n c , m c ) C(n_c,m_c) 中的列等于矩阵 B ( n b , m b ) B(n_b,m_b) 中的列,即 m c = m b m_c=m_b
矩阵乘法的公式: 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)}
( 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. 满足结合律
    ( A B ) C = A ( B C ) (AB)C=A(BC)
    ( λ A ) B = λ ( A B ) + A ( λ B ) (λA)B=λ(AB)+A(λB)
  2. 满足分配律
    A ( B ± C ) = A B ± A C A(B±C)=AB±AC (左分配律)
    ( B ± C ) A = B A ± C A (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
数字快速幂代码:

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 两个 L L 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;
}
发布了27 篇原创文章 · 获赞 13 · 访问量 1697

猜你喜欢

转载自blog.csdn.net/weixin_43855330/article/details/103394783