学《高等代数》第二章的时候过来搜了搜模板,结果真搜到了。于是水一篇题解。

本文部分内容来自《高等代数》。


行列式定义

对于一个 \(n\) 阶行列式

\[A_{n \times n}=
\begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & \ddots & \vdots \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix}\]

其结果为所有不同行不同列的元素乘积的代数和。用数学语言写为:

\[\sum_{j_1j_2 \cdots j_n} (-1) ^ {\tau(j_1j_2\cdots j_n)} a_{1j_1}a_{2j_2}\cdots a_{nj_n}
\]

其中 \(j_1j_2 \cdots j_n\) 为 \(1 \sim n\) 的一个排列。\(\tau(j_1j_2 \cdots j_n)\) 表示排列 \(j\) 的逆序数的个数。

可以看出,如果 \(\tau(j_1 \sim j_n)\) 为偶数,那么该排列对答案的贡献为正。否则为负。

行列式性质

《高代》里原本有七条性质,这里只证明有用的五条。

  • 性质一:行列式转置后值不变。即:
\[\begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & \ddots & \vdots \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix} =

\begin{vmatrix}
a_{11}& a_{21}& \cdots & a_{n1} \\
a_{12}& a_{22}& \cdots & a_{n2} \\
\vdots & \vdots & \ddots & \vdots \\
a_{1n}& a_{2n}& \cdots & a_{nn}
\end{vmatrix} \]

  • 性质二:行列式内某一行的公因子可以提出。
\[\begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & & \vdots \\
ka_{i1} & ka_{i2} & \cdots & ka_{in} & \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix} =
k
\begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & & \vdots \\
a_{i1} & a_{i2} & \cdots & a_{in} & \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix}
\]

证明:

首先考虑 \(n\) 级行列式的 \(n!\) 项。如果把他们分成 \(n\) 组,一定有一种方案,使得第 \(1\) 组中都含有 \(a_{i1}\),第 \(2\) 组中都含有 \(a_{i2}\),以此类推。如果第 \(j\) 项提出 \(a_{ij}\) 后记作 \(A_{ij}\),那么有

\[\begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & & \vdots \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix} =
a_{i1}A_{i1} + a_{i2}A_{i2} + \cdots + a_{in}A_{in} \\
= \sum_{j = 1}^{n} a_{ij}A_{ij}
\]

这将方便我们后面的讨论。

现在证明性质二:

\[\begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & & \vdots \\
ka_{i1} & ka_{i2} & \cdots & ka_{in} & \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix} =

ka_{i1}A_{i1} + ka_{i2}A_{i2} + \cdots + ka_{in}A_{in} \\
= k(a_{i1}A_{i1} + a_{i2}A_{i2} + \cdots + a_{in}A_{in})
= k
\begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & & \vdots \\
a_{i1} & a_{i2} & \cdots & a_{in} \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix}
\]

  • 性质三:
\[\begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & & \vdots \\
b_1 + c_1 & b_2 + c_2 & \cdots & b_n + c_n \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix} \\

=
\begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & & \vdots \\
b_1 & b_2 & \cdots & b_n \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix} +
\begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & & \vdots \\
c_1 & c_2 & \cdots & c_n \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix}
\]

证明:

原行列式可写成 \((b_1 + c_1)A_{i1} + (b_2 + c_2)A_{i2} + \cdots + (b_n + c_n)A_{in}\),这等于右式。

  • 性质四:把第 \(k\) 行的倍数加到第 \(i\) 行,行列式不变。

证明太容易而公式又太难打,就不写了。

  • 性质五:对调行列式的两行,行列式反号。

证明:

\[\begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & & \vdots \\
a_{i1} & a_{i2} & \cdots & a_{in} \\
\vdots & \vdots & &\vdots \\
a_{k1} & a_{k2} & \cdots &a_{kn} \\
\vdots & \vdots & &\vdots \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix} = \begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & & \vdots \\
a_{i1} + a_{k1}& a_{i2} + a_{k2}& \cdots & a_{in} + a_{kn}\\
\vdots & \vdots & &\vdots \\
a_{k1} & a_{k2} & \cdots &a_{kn} \\
\vdots & \vdots & &\vdots \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix} \\
= \begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & & \vdots \\
a_{i1} + a_{k1}& a_{i2} + a_{k2}& \cdots & a_{in} + a_{kn}\\
\vdots & \vdots & &\vdots \\
-a_{i1} & -a_{i2} & \cdots & -a_{in} \\
\vdots & \vdots & &\vdots \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix} \\
= \begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & & \vdots \\
a_{k1} & a_{k2} & \cdots & a_{kn}\\
\vdots & \vdots & &\vdots \\
-a_{i1} & -a_{i2} & \cdots & -a_{in} \\
\vdots & \vdots & &\vdots \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix} \\
= - \begin{vmatrix}
a_{11}& a_{12}& \cdots & a_{1n} \\
a_{21}& a_{22}& \cdots & a_{2n} \\
\vdots & \vdots & & \vdots \\
a_{k1} & a_{k2} & \cdots & a_{kn}\\
\vdots & \vdots & &\vdots \\
a_{i1} & a_{i2} & \cdots & a_{in} \\
\vdots & \vdots & &\vdots \\
a_{n1}& a_{n2}& \cdots & a_{nn}
\end{vmatrix}
\]

其中第一步是利用性质四,将第 \(k\) 行加到了第 \(i\) 行上。

第二步是利用性质四,将第 \(i\) 行减去第 \(k\) 行。

第三步是利用性质四,将第 \(i\) 行加到了第 \(k\) 行上。

最后一步是利用性质二,将第 \(i\) 行提出 \(-1\)。

证毕。

特殊的行列式

  1. 对角行列式

形如

\(\begin{vmatrix}
a_{11} & 0 & \cdots & 0 \\
0 & a_{22} & \cdots & 0 \\
\vdots & \vdots & \ddots & \vdots \\
0 & 0 & \cdots & a_{nn}
\end{vmatrix}\)

的行列式称为对角行列式。其结果为 \(a_{11} \times a_{22} \cdots a_{nn}\)

  1. 三角行列式

形如 \(\begin{vmatrix}
a_{11} & a_{12} & \cdots & a_{1n} \\
0 & a_{22} & \cdots & a_{2n} \\
\vdots & \vdots & & \vdots \\
0 & 0 & 0 & a_{nn} \\
\end{vmatrix}\) 的行列式被称为三角行列式,其结果与对角行列式相同。

行列式计算

显然,如果按照定义,我们需要 \(O(n \times n!)\) 的复杂度。显然无法接受。

由于存在一些特殊的行列式,可以考虑将原行列式转化为三角行列式后求值。思路就是将原行列式利用性质一到四进行转化。

例如有行列式 \(\begin{vmatrix}
2 & 3 & 5 \\
3 & 4 & 7 \\
4 & 3 & 2
\end{vmatrix}\),首先可以将 \(2 \sim 3\) 行分别加上第一行的 \(-\dfrac{3}{2}, -2\) 倍,化为 \(\begin{vmatrix}
2 & 3 & 5 \\
0 & -\dfrac{1}{2} & -\dfrac{1}{2} \\
0 & -3 & -8
\end{vmatrix}\)。

接下来,把第三行加上第二行的 \(-6\) 倍,可得 \(\begin{vmatrix}
2 & 3 & 5 \\
0 & -\dfrac{1}{2} & -\dfrac{1}{2} \\
0 & 0 & -5
\end{vmatrix}\)

于是原式化为了一个三角行列式。对角线乘积即为答案 \(5\)。

这个方法类似高斯消元的过程。因此就把它叫做高斯消元吧。

可以看出,这个方法的时间复杂度是 \(O(n ^ 3)\) 的,完全可以接受。

带模数行列式计算

如果带模数怎么算行列式的值呢?

有一种方法叫做辗转相减法,可以完美的解决这个问题。

比如有行列式 \(\begin{vmatrix}
3 & 2\\
4 & 1
\end{vmatrix}\),首先先用第二行的第一个数除以第一行第一个数,得到 \(1\)。(这里是下取整)。

然后用第二行减去第一行 \(\times 1\),得到 \(\begin{vmatrix}
3 & 2\\
1 & -1
\end{vmatrix}\)

容易证明第二行第一个数在操作完之后一定小于第一行第一个数。因此交换 \(1, 2\) 行,得到 \(-\begin{vmatrix}
1 & -1\\
3 & 2
\end{vmatrix}\)。

重复上述操作,直到第一行为 \(0\)。得到这样的行列式:\(\begin{vmatrix}
0 & 5\\
1 & -1
\end{vmatrix}\)。

最后再把一、二行交换即可得到下三角行列式:

\[-\begin{vmatrix}
1 & -1\\
0 & 5
\end{vmatrix}\]

答案即为 \(-5\)。

由于在辗转相减的过程中可以取模,所以这个问题就被完美解决了。

分析一下复杂度。易证辗转相减的复杂度与欧几里得算法类似,为 \(O(\log n)\) 级别。如果记交换两行复杂度为 \(O(n)\),那么总复杂度就为 \(O(n ^ 2(\log n + n))\)。

注意:两行交换时千万别忘变号!!!

代码

#include <algorithm>
#include <cstdio>
#define int long long using namespace std; const int N = 610;
int n, p, w[N][N], f;
void Swap(int &a, int &b) {
for (int i = 1; i <= n; i ++ )
swap(w[a][i], w[b][i]);
f ^= 1; // 变号
}
int gauss() {
for (int i = 1; i <= n; i ++ )
for (int j = i + 1; j <= n; j ++ ) {
while (w[i][i]) {
int K = (int)w[j][i] / w[i][i];
for (int k = i; k <= n; k ++ )
((w[j][k] -= K * w[i][k] % p) += p) %= p;
Swap(i, j);
} Swap(i, j);
}
int ans = 1;
for (int i = 1; i <= n; i ++ )
(ans *= w[i][i]) %= p;
return (f ? (-ans + p) % p : (ans + p) % p);
} signed main() {
scanf("%lld%lld", &n, &p);
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
scanf("%lld", &w[i][j]);
return 0 & printf("%lld\n", gauss());;
}

本文公式很多,可能有笔误。希望大家可以指出。

P7112 【模板】行列式求值的更多相关文章

  1. 洛谷P7112 行列式求值

    行列式求值 这是一个让你掉头发的模板题 行列式的定义 行列式 (\(\texttt{Determinant}\)) 是一个函数定义,取值是一个标量. 对一个 \(n\times n\) 的矩阵 \(A ...

  2. 高斯消元与行列式求值 part1

    两道模板题,思路与算法却是相当经典. 先说最开始做的行列式求值,题目大致为给一个10*10的行列式,求其值 具体思路(一开始看到题我的思路): 1.暴算,把每种可能组合试一遍,求逆序数,做相应加减运算 ...

  3. U66785 行列式求值

    二更:把更多的行列式有关内容加了进来(%%%%%Jelly Goat奆佬) 题目描述 给你一个N(n≤10n\leq 10n≤10)阶行列式,请计算出它的值 输入输出格式 输入格式: 第一行有一个整数 ...

  4. 基于上三角变换或基于DFS的行(列)展开的n阶行列式求值算法分析及性能评估

    进入大一新学期,看完<线性代数>前几节后,笔者有了用计算机实现行列式运算的想法.这样做的目的,一是巩固自己对相关概念的理解,二是通过独立设计算法练手,三是希望通过图表直观地展现涉及的两种算 ...

  5. C语言求行列式的值

    #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <window ...

  6. 洛谷P5282 【模板】快速阶乘算法(多项式多点求值+MTT)

    题面 传送门 前置芝士 \(MTT\),多项式多点求值 题解 这题法老当初好像讲过--而且他还说这种题目如果模数已经给定可以直接分段打表艹过去 以下是题解 我们设 \[F(x)=\prod_{i=0} ...

  7. 表达式求值(二叉树方法/C++语言描述)(一)

    使用二叉树对算数表达式(以下简称为表达式)进行求值,实质上是将表达式转换为二叉树,对其进行后序遍历,得到后缀表达式的同时可以求得表达式的值.转换和求值的过程也需要借助数据结构栈的帮助. 二叉树数据结构 ...

  8. 表达式求值(栈方法/C++语言描述)(一)

    一个算数表达式(以下简称为表达式)由运算数.运算符.左括号和右括号组成,定义一个枚举类型TokenType表示为: typedef enum { BEGIN, NUMBER, OPERATOR, LE ...

  9. Herding(hdu4709)三点运用行列式求面积

    Herding Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  10. c++11实现l延迟调用(惰性求值)

    惰性求值 惰性求值一般用于函数式编程语言中,在使用延迟求值的时候,表达式不在它被绑定到变量之后就立即求值,而是在后面的某个时候求值.     可以利用c++11中的std::function, lam ...

随机推荐

  1. .NET Core使用SkiaSharp快速生成二维码( 真正跨平台方案)

    前言 在.NET 6之前我们一直是使用QRCoder来生成二维码(QRCoder是一个非常强大的生成二维码的组件,用到了System.Drawing.Common 包),然后从.NET 6开始,当为非 ...

  2. linux的认知与基本命令

    一.linux的了解 1. 什么是Linux?       a,Linux是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年10月5日首次发布.它主要受到Mi ...

  3. interface 接口相关【GO 基础】

    〇.接口简介 接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节.也就是说,接口可以将一种或多种特征归纳到一起,其他不同的对象通过实现此接口,来表示可以 ...

  4. 03-11gR2单机通过RMAN恢复到RAC(未验证)

    1.在单机上做一个完全备份,并将备份集拷贝到RAC的第一个节点上. 2.强行启动到nomount 3.恢复spfile 4.创建pfile,修改pfile,重建spfile #####修改contro ...

  5. Node.js中常用的设计模式有哪些?

    本文由葡萄城技术团队首发.转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 设计模式简介 设计模式是由经验丰富的程序员在日积月累中抽象出的用以解决通用问题的可 ...

  6. mysql出现10061错误解决方法

    首先要关闭MYSQL服务 关闭你现在正在运行的mysql数据库,用结束mysql进程或者直接关闭mysql服务器都可以 1.开始菜单->运行(cmd)->寻径到MySQL文件中的bin目录 ...

  7. LVS负载均衡概念+三种模式

    1.LVS负载均衡概念剖解: 1)LVS技术全称:Linux virtual Server ,Linux虚拟机服务器集群,1998由章文嵩博士设计.并且开源的,是中国最早的开源软件项目之一.   2) ...

  8. unity UGUI 正交相机实现图片的透视旋转效果

    UI透视效果常见的就是绕x轴或y轴旋转,来达到近大远小的效果.正经要做透视UI的话肯定直接用透视相机,如果透视效果用的极少(就一张图)不改动相机类型才按这种思路进行. 最简单直接的想法就是把矩形的图片 ...

  9. Golang后端大厂面经!

    大家好,我是阳哥.专注Go语言的学习经验分享和就业辅导. 之前分享了很多 Golang 后端的大厂面经,不少同学在催更新,这篇给大家继续安排. 本文来自一位同学的投稿,面试深X服的面经汇总,前半部分主 ...

  10. 【慢SQL性能优化】 一条SQL的生命周期

    一. 一条简单SQL在MySQL执行过程 一张简单的图说明下,MySQL架构有哪些组件和组建间关系,接下来给大家用SQL语句分析 例如如下SQL语句 SELECT department_id FROM ...