文章目录

线性代数基础 Linear Algebra Basics

线性代数基础 \(Linear Algebra Basics\)

向量

向量定义

一个 \(n\) 维向量 \(V\) 可以表示为:

\[V = (v_1, v_2, \dots, v_n) \]

点积运算

两个 \(n\) 维向量 \(p\)\(q\) 的点积:

\[p \cdot q = \sum_{i=1}^n p_i q_i \]

示例

\[\begin{aligned} p &= (1, 2, 3) \\ q &= (4, 5, 6) \\ p \cdot q &= 1 \times 4 + 2 \times 5 + 3 \times 6 = 32 \end{aligned} \]

矩阵

矩阵定义

一个 \(m \times n\) 的矩阵 \(A\)

\[A = \begin{pmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \end{pmatrix} \]

特殊矩阵

单位矩阵 \(I_n\)

\[I_n = \begin{pmatrix} 1 & 0 & \cdots & 0 \\ 0 & 1 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & 1 \end{pmatrix} \]

矩阵运算

矩阵加法

\[(A + B)_{ij} = A_{ij} + B_{ij} \]

矩阵数乘

\[(kA)_{ij} = k \cdot A_{ij} \]

矩阵乘法

对于 \(A_{m \times n}\)\(B_{n \times p}\)

\[(AB)_{ij} = \sum_{k=1}^n A_{ik} B_{kj} \]

注意 : 矩阵乘法不满足交换律 !!!

再说一遍 :矩阵乘法不满足交换律 !!!

最后一遍 :矩阵乘法不满足交换律 !!!

示例

\[\begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix} \begin{pmatrix} 5 & 6 \\ 7 & 8 \end{pmatrix} = \begin{pmatrix} 1 \times 5 + 2 \times 7 & 1 \times 6 + 2 \times 8 \\ 3 \times 5 + 4 \times 7 & 3 \times 6 + 4 \times 8 \end{pmatrix} = \begin{pmatrix} 19 & 22 \\ 43 & 50 \end{pmatrix} \]


代码模板

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int N = 500 + 5;
const int MOD = 1e9 + 7;

int n, p, m;
int A[N][N], B[N][N], C[N][N];

void read() {
	cin >> n >> p >> m;

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= p; j++) {
			cin >> A[i][j];
			A[i][j] = (A[i][j] % MOD + MOD) % MOD;
		}
	}

	for (int i = 1; i <= p; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> B[i][j];
			B[i][j] = (B[i][j] % MOD + MOD) % MOD;
		}
	}
}

void mul() {
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			ll sum = 0;
			for (int k = 1; k <= p; k++) {
				sum += (1ll * A[i][k] * B[k][j]) % MOD;
				sum %= MOD;
			}
			
			C[i][j] = sum;
		}
	}
}

void print() {
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cout << C[i][j] << " ";
		}
		
		cout << "\n";
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	read();
	
	mul();
	
	print();

	return 0;
}

矩阵转置

\[(A^T)_{ij} = A_{ji} \]

矩阵快速幂

定义

对于方阵 \(A\)

\[A^k = \underbrace{A \times A \times \cdots \times A}_{k \text{次}} \]

快速算法

利用二进制分解:

\[A^k = \prod_{i=0}^{\lfloor \log_2 k \rfloor} A^{2^i} \]


代码模板

#include <bits/stdc++.h>
using namespace std;

const int N = 1e2 + 3;
const int MOD = 1e9 + 7;

struct Matrix {
	int n;
	int mat[N][N];
	
	Matrix(int _n = 0) : n(_n) { memset(mat, 0, sizeof(mat)); }

	void E() { for (int i = 1; i <= n; i ++) mat[i][i] = 1; }
};

Matrix mul(Matrix a, Matrix b) {
	int n = a.n;
	Matrix ret(n);
	
	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j <= n; j ++) {
			for (int k = 1; k <= n; k ++) {
				ret.mat[i][j] = (ret.mat[i][j] + 1ll * a.mat[i][k] * b.mat[k][j]) % MOD;
			}
		}
	}
	
	return ret;
}

Matrix quick_pow(Matrix x, long long p) {
	int n = x.n;
	Matrix ret(n);
	ret.E();
	
	while (p) {
		if (p & 1) ret = mul(ret, x);
		x = mul(x, x);
		p >>= 1;
	}
	
	return ret;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	int n;
	long long k;
	cin >> n >> k;
	Matrix a(n);

	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j <= n; j ++) {
			cin >> a.mat[i][j];
			a.mat[i][j] = (a.mat[i][j] % MOD + MOD) % MOD;
		}
	}

	Matrix res = quick_pow(a, k);

	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j <= n; j ++) {
			cout << res.mat[i][j] << ' ';
		}
		cout << '\n';
	}

	return 0;
}

常系数齐次线性递推与矩阵加速 !!!

一、线性递推的数学本质

1. 递推关系的矩阵表示

对于k阶线性递推关系:

\[f_n = \sum_{i=1}^k c_i f_{n-i} \quad (n > k) \]

存在转移矩阵 \(A\) 满足:

\[\underbrace{ \begin{bmatrix} f_n \\ f_{n-1} \\ \vdots \\ f_{n-k+1} \end{bmatrix} }_{V_n} = A \times \underbrace{ \begin{bmatrix} f_{n-1} \\ f_{n-2} \\ \vdots \\ f_{n-k} \end{bmatrix} }_{V_{n-1}} \]

2. 转移矩阵的结构特性

矩阵 \(A\) 具有如下标准形式:! ! !

\[A = \begin{bmatrix} c_1 & c_2 & \cdots & c_{k-1} & c_k \\ 1 & 0 & \cdots & 0 & 0 \\ 0 & 1 & \cdots & 0 & 0 \\ \vdots & \vdots & \ddots & \vdots & \vdots \\ 0 & 0 & \cdots & 1 & 0 \end{bmatrix}_{k \times k} \]

构造原理

- 第一行:直接对应递推系数

- 次对角线:全1元素用于"移位"记录历史状态


二、矩阵加速的严格推导

1. 递推展开过程

通过递归展开可得:

\[V_n = A \times V_{n-1} = A^2 \times V_{n-2} = \cdots = A^{n-k} \times V_k \]

其中初始向量:

\[V_k = \begin{bmatrix} f_k \\ f_{k-1} \\ \vdots \\ f_1 \end{bmatrix} \]

2. 时间复杂度分析

计算过程分为两步:

  1. 计算矩阵幂 \(A^{n-k}\)
    • 使用快速幂算法
    • 每次矩阵乘法 \(O(k^3)\) 时间
    • 总时间 \(O(k^3 \log n)\)
  2. 矩阵-向量乘法
    • \(O(k^2)\) 时间

三、推广到非齐次情况

1. 含常数项的递推

对于递推式:

\[f_n = \sum_{i=1}^k c_i f_{n-i} + d \]

构造技巧

  • 升维处理:

    \[\widetilde{V}_n = \begin{bmatrix} V_n \\ 1 \end{bmatrix} = \begin{bmatrix} f_n \\ \vdots \\ f_{n-k+1} \\ 1 \end{bmatrix} \]

  • 扩展转移矩阵:

    \[\widetilde{A} = \begin{bmatrix} A & \begin{matrix} d \\ 0 \\ \vdots \\ 0 \end{matrix} \\ 0 \cdots 0 & 1 \end{bmatrix} \]

2. 含多项式项的递推

对于递推式:

\[f_n = \sum_{i=1}^k c_i f_{n-i} + P(m) \]

其中 \(P(m)\)\(m\) 次多项式
构造方法

  • 需要跟踪的变量:
    • \(f_n\) 及其历史项
    • \(m^j \ (j=0,1,...,m)\)
  • 转移矩阵维度:
    • 总维度 \(= k + (m + 1)\)

四、典型例题的解析理论

例题1:三阶递推问题

给定:

\[f_n = f_{n-1} + f_{n-3} \quad (n \geq 4) \]

初始条件:\(f_1=f_2=f_3=1\)

矩阵构造过程

确定状态向量:

\[V_n = \begin{bmatrix} f_n \\ f_{n-1} \\ f_{n-2} \end{bmatrix} \]

建立方程关系:

\[\begin{cases} f_n = 1·f_{n-1} + 0·f_{n-2} + 1·f_{n-3} \\ f_{n-1} = 1·f_{n-1} + 0·f_{n-2} + 0·f_{n-3} \\ f_{n-2} = 0·f_{n-1} + 1·f_{n-2} + 0·f_{n-3} \end{cases} \]

得到转移矩阵:

\[A = \begin{bmatrix} 1 & 0 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \end{bmatrix} \]

求解步骤

计算幂次:

\[power = n - 3 \]

最终表达式:

\[\begin{bmatrix} f_n \\ f_{n-1} \\ f_{n-2} \end{bmatrix} = A^{n-3} \times \begin{bmatrix} f_3 \\ f_2 \\ f_1 \end{bmatrix} \]


五、理论边界与限制

1. 适用条件

  • 必须严格满足线性关系
  • 系数必须为常数(不能是 \(n\) 的函数)

2. 不适用情况

  • 非线性递推:

    \[f_n = f_{n-1} \times f_{n-2} \]

  • 变系数递推:

    \[f_n = n \cdot f_{n-1} \]

3. 维度爆炸问题

当递推式中包含:

  • 多个多项式项
  • 高次多项式时

会导致转移矩阵维度急剧增加,实际应用中需权衡:

\[\text{矩阵维度} = k + \sum_{i=1}^m (\deg(P_i) + 1) \]


六、理论延伸

1. 与特征根法的联系

矩阵特征多项式:

\[\det(\lambda I - A) = 0 \]

正是递推关系的特征方程,二者通解形式一致。

2. 广义矩阵加速

对于分块矩阵情形,可处理:

  • 多个相互关联的递推式
  • 二维递推问题
  • 带有模运算的特殊递推

代码模板

#include <bits/stdc++.h>
using namespace std;

using ll = long long;

const int MOD = 1e9 + 7;
const int N = 5;

struct Matrix {
	int n;
	int mat[N][N];

	Matrix(int _n = 0) : n(_n) { memset(mat, 0, sizeof(mat)); }

	void E() { for (int i = 1; i <= n; i++) mat[i][i] = 1; }
};

Matrix A(3), init(3);

void pre() {
	A.mat[1][1] = 1;
	A.mat[1][3] = 1;
	A.mat[2][1] = 1;
	A.mat[3][2] = 1;

	init.mat[1][1] = 1;
	init.mat[2][1] = 1;
	init.mat[3][1] = 1;
}

Matrix mul(Matrix a, Matrix b) {
	int n = a.n;
	Matrix ret(n);

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			for (int k = 1; k <= n; k++) {
				ret.mat[i][j] = (ret.mat[i][j] + 1ll * a.mat[i][k] * b.mat[k][j]) % MOD;
			}
		}
	}

	return ret;
}

Matrix quick_pow(Matrix x, ll p) {
	int n = x.n;
	Matrix ret(n);
	ret.E();

	while (p) {
		if (p & 1) ret = mul(ret, x);
		x = mul(x, x);
		p >>= 1;
	}

	return ret;
}

void solve(int n) {
	if (n <= 3) {
		cout << "1\n";
		return;
	}

	Matrix ret = quick_pow(A, n - 3);
	Matrix ans = mul(ret, init);

	cout << ans.mat[1][1] << '\n';
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	int T; cin >> T;
	
	pre();
	
	while (T--) {
		int n; cin >> n;
		
		solve(n);
	}

	return 0;
}

线性方程组

增广矩阵表示

方程组:

\[\begin{cases} a_{11}x_1 + a_{12}x_2 + \cdots + a_{1n}x_n = b_1 \\ a_{21}x_1 + a_{22}x_2 + \cdots + a_{2n}x_n = b_2 \\ \vdots \\ a_{m1}x_1 + a_{m2}x_2 + \cdots + a_{mn}x_n = b_m \end{cases} \]

增广矩阵:

\[\left( \begin{array}{cccc|c} a_{11} & a_{12} & \cdots & a_{1n} & b_1 \\ a_{21} & a_{22} & \cdots & a_{2n} & b_2 \\ \vdots & \vdots & \ddots & \vdots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} & b_m \end{array} \right) \]

高斯消元法

基本操作

  1. 交换两行
  2. 某行乘以非零常数
  3. 将某行的倍数加到另一行

消元步骤

  1. 化为上三角矩阵
  2. 回代求解

示例

\[\begin{aligned} &\left( \begin{array}{ccc|c} 1 & 1 & 1 & 6 \\ 2 & 1 & 1 & 10 \\ 1 & 2 & 1 & 10 \end{array} \right) \\ \rightarrow &\left( \begin{array}{ccc|c} 1 & 1 & 1 & 6 \\ 0 & -1 & -1 & -2 \\ 0 & 1 & 0 & 4 \end{array} \right) \\ \rightarrow &\left( \begin{array}{ccc|c} 1 & 0 & 0 & 1 \\ 0 & 1 & 0 & 4 \\ 0 & 0 & 1 & -2 \end{array} \right) \end{aligned} \]

解得:

\[x = 1, \quad y = 4, \quad z = -2 \]


代码模板

#include <bits/stdc++.h>
using namespace std;

const int N = 1e2 + 10;

int n;

double a[N][N];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> n;
	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j <= n + 1; j ++) {
			cin >> a[i][j];
		}
	}
	
	for (int i = 1; i <= n; i ++) {
		int p = i;
		
		while (p <= n && a[p][i] == 0) p ++;
		if (p == n + 1) {
			cout << "No Solution" << '\n';
			return 0;
		}
		
		for (int j = 1; j <= n + 1; j ++)
			swap(a[i][j], a[p][j]);

		double tmp = a[i][i];
		for (int j = 1; j <= n + 1; j ++)
			a[i][j] /= tmp;

		for (int j = 1; j <= n; j ++) {
			if (i == j) continue;
			
			tmp = a[j][i];
			
			for (int k = 1; k <= n + 1; k ++) {
				a[j][k] -= a[i][k] * tmp;
			}
		}
	}
	
	cout << fixed << setprecision(2);
	for (int i = 1; i <= n; i ++)
		cout << a[i][n + 1] << '\n';

	return 0;
}

部分由 AI 润色

posted @ 2026-09-03 14:20  lvwangshu  阅读(18)  评论(0)    收藏  举报