矩阵

矩阵概念

row 行
column 列

单位矩阵

非对角线都是0,对角线上都是1,类似乘法中的1
一般用I表示
单位矩阵乘以任何矩阵A,都等于A本身
AI = IA = A

稀疏矩阵

三角矩阵

对称矩阵

行初等变换

  1. 交换两行
  2. 同一行自乘 k (k非0)
  3. 一行的k倍加到另一行上
    主要用途是矩阵求逆

矩阵加减

矩阵乘法

矩阵转置

矩阵的逆

求矩阵A的逆
矩阵A和单位矩阵连起来组成一个n行2n列的矩阵
通过行初等变换,高斯消元,让矩阵A变成单位矩阵I
做行初等变换时,一共2n列
如果原本的矩阵A变成了单位矩阵,那么原本的单位矩阵就变成了A的逆矩阵

线性相关

矩阵的秩

行列式

特征多项式,特征方程,特征值,特征向量,

CH定理

https://en.wikipedia.org/wiki/Cayley–Hamilton_theorem

参考题目

绝大多数涉及到矩阵的题目都是 矩阵乘法快速幂
少量题目利用矩阵的性质,维护前缀和或线段树

P6009 [USACO20JAN]Non-Decreasing Subsequences P

https://www.luogu.com.cn/problem/P6009

题目描述

Bessie 最近参加了一场 USACO 竞赛,遇到了以下问题。当然 Bessie 知道怎么做。那你呢?

考虑一个仅由范围在 1K1 \ldots K1K201 \leq K \leq 20)之间的整数组成的长为 NN 的序列 A1,A2,,ANA_1,A_2, \ldots ,A_N1N5×1041 \leq N \leq 5 \times 10^4)。给定 QQ1Q2×1051 \leq Q \leq 2 \times 10^5 )个形式为 [Li,Ri][L_i,R_i]1LiRiN1 \leq L_i \leq R_i \leq N)的询问。对于每个询问,计算 ALi,ALi+1,,ARiA_{L_i},A_{L_i+1}, \ldots ,A_{R_i} 中不下降子序列的数量模 109+710^9+7 的余数。

AL,,ARA_L,\ldots ,A_R 的一个不下降子序列是一组索引 (j1,j2,,jxj_1,j_2, \ldots ,j_x),满足 Lj1<j2<<jxRL\le j_1<j_2<\ldots<j_x\le R 以及 Aj1Aj2AjxA_{j_1}\le A_{j_2}\le \ldots \le A_{j_x}。确保你考虑了空子序列!

输入格式

输入的第一行包含两个空格分隔的整数 NNKK

第二行包含 NN 个空格分隔的整数 A1,A2,,ANA_1,A_2, \ldots ,A_N

第三行包含一个整数 QQ

以下 QQ 行每行包含两个空格分隔的整数 LiL_iRiR_i

输出格式

对于每个询问 [Li,Ri][L_i,R_i],你应当在新的一行内输出 ALi,ALi+1,,ARiA_{L_i},A_{L_i+1},\ldots, A_{R_i} 的不下降子序列的数量模 109+710^9+7 的余数。

样例 #1

样例输入 #1
5 2
1 2 1 1 2
3
2 3
4 5
1 5
样例输出 #1
3
4
20

提示

样例解释

对于第一个询问,不下降子序列为 ()()(2)(2)(3)(3)(2,3)(2,3) 不是一个不下降子序列,因为 A2≰A3A_2\not \le A_3

对于第二个询问,不下降子序列为 ()()(4)(4)(5)(5)(4,5)(4,5)

子任务

参考代码

#include <bits/stdc++.h>
using namespace std;
int n, m, x;
const int mod = 1000000007;
int p[50020][20][20], q[50020][20][20];
int f[20][20][20];
int g[20][20][20];
void amul(int a[20][20], int b[20][20], int c[20][20])
{
	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < m; j++)
		{
			c[i][j] = 0;
		}
	}
	for (int i = 0; i < m; i++)
	{
		for (int k = 0; k < m; k++)
		{
			if (a[i][k] == 0)
			{
				continue;
			}
			for (int j = 0; j < m; j++)
			{
				c[i][j] = (c[i][j] + (long long)a[i][k] * b[k][j]) % mod;
			}
		}
	}
}
void bmul(int a[20][20], int b[20][20], int c[20][20])
{
	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < m; j++)
		{
			c[i][j] = 0;
		}
	}
	for (int j = 0; j < m; j++)
	{
		for (int k = 0; k < m; k++)
		{
			if (b[k][j] == 0)
			{
				continue;
			}
			for (int i = 0; i < m; i++)
			{
				c[i][j] = (c[i][j] + (long long)a[i][k] * b[k][j]) % mod;
			}
		}
	}
}
int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < m; j++)
		{
			f[i][j][j] = 1;
			g[i][j][j] = 1;
		}
		for (int j = 0; j <= i; j++)
		{
			f[i][j][i] += 1;
			g[i][j][i] = (g[i][j][i] + (mod - 1) / 2) % mod;
		}
	}
	for (int i = 0; i < m; i++)
	{
		p[0][i][i] = 1;
		q[0][i][i] = 1;
	}
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &x);
		x--;
		bmul(p[i - 1], f[x] , p[i]);
		amul(g[x] , q[i - 1], q[i]);
	}
	int t, l, r;
	scanf("%d", &t);
	for (int i = 0; i < t; i++)
	{
		scanf("%d%d", &l, &r);
		l--;
		int ans = 0;
		for (int i = 0; i < m; i++)
		{
			for (int j = 0; j < m; j++)
			{
				ans = (ans + (long long)q[l][0][i] * p[r][i][j]) % mod;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

题解

  1. 矩阵
    1. 矩阵概念
    2. 单位矩阵
    3. 稀疏矩阵
    4. 三角矩阵
    5. 对称矩阵
    6. 行初等变换
    7. 矩阵加减
    8. 矩阵乘法
    9. 矩阵转置
    10. 矩阵的逆
    11. 线性相关
    12. 矩阵的秩
    13. 行列式
    14. 特征多项式,特征方程,特征值,特征向量,
    15. CH定理
    16. 参考题目
      1. P6009 [USACO20JAN]Non-Decreasing Subsequences P