第一章、线性代数(1)矩阵乘法

一、矩阵相关概念

【矩阵】

由n×m个数排成n行m列的数表称为n行m列的矩阵,简称n×m矩阵。记作:

在学习图论时,存储图的一种方式------邻接矩阵,就是矩阵。所以矩阵用二维数组就可以存储。

【特殊的矩阵】

1、方阵

行数等于列数的矩阵称为方阵。方阵中行数等于列数的元素构成主对角线。

2、三角矩阵

如果方阵主对角线左下方的元素均为0,称为上三角矩阵。例如:

如果方阵主对角线右上方的元素均为0,称为下三角矩阵。例如:

3、对角矩阵

主对角线之外的元素均为0的方阵称为对角矩阵。例如:

4、单位矩阵

主对角线的元素均为1的对角矩阵。例如:

【矩阵的运算】

1、加法、减法和数乘

两个矩阵的加减法为对应元素分别作加减法。注意:只有同型矩阵之间可以做对应相加减!

数乘即为矩阵乘以一个数,结果为矩阵中每个元素都乘以这个数。

矩阵的加减与数乘称为矩阵的线性运算。

2、矩阵乘法

矩阵相乘时只有第一个矩阵的列数 与第二个矩阵的行数相同时才有意义!

设A为n×s的矩阵,B为s×m的矩阵,那么矩阵A与矩阵B的乘积为n×m的矩阵C,其中cij表示矩阵A的第i行与矩阵B的第j列元素分别相乘再相加。

【矩阵的运算规律】

1、线性运算满足交换律、结合律、分配律

·A+B = B+A

·A+B+C = A+(B+C)

·k*(A+B)= k*A + k*B

2、矩阵乘法只满足结合律和分配律

·ABC = A(BC)

·A(B+C) = AB + AC

注意:矩阵乘法可能不满足交换律。因此,在计算矩阵乘法时,前后顺序很重要!

特殊的,任何矩阵乘单位矩阵E,都不会改变:AE = EA = A 。因此,单位矩阵相当于数字1。

二、【模板】矩阵乘法

cpp 复制代码
#define  _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;

const int N = 110;

int n, m, s;
int a[N][N], b[N][N], c[N][N];

int main()
{
	cin >> n >> m >> s;

	for (int i = 1;i <= n;i++)
		for (int j = 1;j <= m;j++)
			cin >> a[i][j];

	for (int i = 1;i <= m;i++)
		for (int j = 1;j <= s;j++)
			cin >> b[i][j];

	for (int i = 1;i <= n;i++)
	{
		for (int j = 1;j <= s;j++)
		{
			for (int k = 1;k <= m;k++)
			{
				c[i][j] += a[i][k] * b[k][j];
			}
		}
	}

	for (int i = 1;i <= n;i++)
	{
		for (int j = 1;j <= s;j++)
		{
			cout << c[i][j] << " ";
		}
		cout << endl;
	}

	return 0;
}

三、【模板】矩阵快速幂

cpp 复制代码
#define  _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <cstring>
using namespace std;

typedef long long LL;
const int N = 110, mod = 1e9 + 7;

LL k, n;

// 矩阵的结构体
struct matrix
{
	LL m[N][N];

	// 构造函数
	matrix()
	{
		memset(m, 0, sizeof m);
	}

	// 重载乘法运算符
	matrix operator*(const matrix& B) const
	{
		matrix C;
		for (int i = 1;i <= n;i++)
		{
			for (int j = 1;j <= n;j++)
			{
				for (int k = 1;k <= n;k++)
				{
					C.m[i][j] = (C.m[i][j] + m[i][k] * B.m[k][j]) % mod;
				}
			}
		}
		return C;
	}

}A, RET;

void qpow(LL b)
{
    // 把RET变为单位矩阵
	for (int i = 1;i <= n;i++)
		RET.m[i][i] = 1;

	while (b)
	{
		if (b & 1)
		{
			RET = RET * A;
		}

		b >>= 1;
		A = A * A;
	}
}

int main()
{
	cin >> n >> k;
	for (int i = 1;i <= n;i++)
		for (int j = 1;j <= n;j++)
			cin >> A.m[i][j];

	qpow(k);

	for (int i = 1;i <= n;i++)
	{
		for (int j = 1;j <= n;j++)
		{
			cout << RET.m[i][j] << " ";
		}
		cout << endl;
	}

	return 0;
}

四、【练习】矩阵加速

解法:利用矩阵快速幂加速递推,构造出矩阵相乘的形式。

cpp 复制代码
#define  _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <cstring>
using namespace std;

typedef long long LL;
const int N = 5, mod = 1e9 + 7;

struct matrix
{
	LL m[N][N];

	matrix()
	{
		memset(m, 0, sizeof m);
	}

	matrix operator*(const matrix& B) const
	{
		matrix C;
		for (int i = 1;i <= 3;i++)
		{
			for (int j = 1;j <= 3;j++)
			{
				for (int k = 1;k <= 3;k++)
				{
					C.m[i][j] = (C.m[i][j] + m[i][k] * B.m[k][j]) % mod;
				}
			}
		}
		return C;
	}

	void clear()
	{
		memset(m, 0, sizeof m);
	}

}A, RET;

void qpow(LL b)
{
	RET.m[1][1] = RET.m[1][2] = RET.m[1][3] = 1;
	A.m[1][1] = A.m[1][2] = A.m[2][3] = A.m[3][1] = 1;

	while (b)
	{
		if (b & 1)
			RET = RET * A;

		b >>= 1;
		A = A * A;
	}
}

int main()
{
	int T;
	cin >> T;
	while (T--)
	{
		int n;
		cin >> n;

		A.clear();
		RET.clear();

		if (n == 1 || n == 2 || n == 3)
		{
			cout << 1 << endl;
			continue;
		}

		qpow(n - 3);

		cout << RET.m[1][1] << endl;
	}

	return 0;
}
相关推荐
爱刷碗的苏泓舒21 小时前
RTKLIB Neville 插值法:源码推导与 GNSS 精密轨道应用
线性代数·rtklib·内维尔算法·neville
小飞象—木兮1 天前
经营分析核心思路:经营分析的六层执行框架、底层原则、 全行业通用经营分析方法论
大数据·人工智能·矩阵·数据分析·用户运营
javaDocker1 天前
从「五个窗口」到「一条流水线」:金融核心交易测试的 AI 协作矩阵设计
人工智能·金融·矩阵·研发效能·ai自测
坐看风云变幻1 天前
《飞控数学与控制 · 新手入门连载》第 1 期|线性代数入门:向量、矩阵与旋转矩阵 SO(3)
线性代数·矩阵·飞控·旋转矩阵
智行合一科技2 天前
CTR报告:AI营销成广告增长引擎,GEO与AIGC矩阵营销成破局关键
人工智能·矩阵·aigc
烂蜻蜓3 天前
Matplotlib入门教程(十三):imshow() 详解——灰度图、彩色图、热力图与矩阵可视化
线性代数·矩阵·matplotlib
没有钱的钱仔4 天前
协方差矩阵含义
算法·机器学习·矩阵
爱刷碗的苏泓舒4 天前
泰勒级数与泰勒展开:GNSS卫地距线性化、Jacobian矩阵与Hessian矩阵
线性代数·算法·矩阵·gnss·雅可比矩阵·卫地距线性化·海森矩阵
lhh_qrsly5 天前
机器学习 深度学习 强化学习 都学啥 和 高等数学 线性代数 概率论数理统计 有啥关系
深度学习·线性代数·机器学习
tigershang5 天前
亲手拆开 Transformer:从手算入门到理论全景
神经网络·ai·矩阵·transformer