行列式求值,从 $n!$ 优化到 $n^3$
前置知识
- \(\sum\) 为累加符号,\(\prod\) 为累乘符号。
- 上三角矩阵指只有对角线及其右上方有数值其余都是 \(0\) 的矩阵。
- 如果一个矩阵的对角线全部为 \(1\) 那么这个矩阵为单位矩阵记作 \(I\)。
- 对于矩阵 \(A_{n,m}\) 和矩阵 \(B_{m,n}\) 满足 \(A_{i,j}=B_{j,i}\) 记作 \(A=B^T\)。
- 如果 \(i,j\in[1,n]\) 满足 \(i<j\) 且 \(p_i>p_j\),那么称 \((p_i,p_j)\) 为一对逆序对。
- 假设 \(p\) 是一个排列,那么 \(\tau(p)\) 为 \(p\) 中逆序对的个数。
定义
行列式 \(A\) 为 \(n\) 阶方阵,那么 \(|A|\) 为该矩阵的行列式,记作 \(\operatorname{det}(A)\)。
a_{1,1} & a_{1,2} &\cdots & a_{1,n} \\
a_{2,1} & a_{2,2} &\cdots & a_{2,n} \\
\cdots & \cdots &\cdots & \cdots \\
a_{n,1} & a_{n,2} &\cdots & a_{n,n} \\
\end{vmatrix}=\sum_{j_1,j_2,\cdots ,j_n}(-1)^{N(j_1,j_2,\cdots ,j_n)}\prod_{i=1}^n a_{i,j_i}\]
几何意义
对于一个 \(n\) 维的向量空间中的 \(n\) 个向量,我们可以构造一个 \(n\) 阶行列式。这个行列式的绝对值等于由这 \(n\) 个向量所构成的平行体的体积。
具体来说,如果我们有 \(n\) 个向量 \(\vec{v_1}, \vec{v_2}, ..., \vec{v_n}\),我们可以将这些向量的坐标构造成一个n阶行列式:
v_{1,1} & v_{1,2} & \cdots & v_{1,n} \\
v_{2,1} & v_{2,2} & \cdots & v_{2,n} \\
\cdots & \cdots & \cdots & \cdots \\
v_{n,1} & v_{n,2} & \cdots & v_{n,n} \\
\end{bmatrix}
\]
其中,\(v_{ij}\) 是向量 \(\vec{v_i}\) 的第 \(j\) 个坐标。这个行列式的绝对值就是由向量 \(\vec{v_1}, \vec{v_2}, ..., \vec{v_n}\) 所形成的平行体的体积。
求解
暴力
首先有一个粗暴的做法单纯是根据定义求解的,虽然无法应用到那时有助于理解定义。
要求解行列式首先需要随机选择一行,为了方便说明不妨取第一行。那么在这一行的第 \(i\) 个元素的贡献为 \((-1)^{1+i}\times 1\times\) 不看这一行和这一列剩余的矩阵。
\]
通过这个操作,我们就将这个行列式降阶了,接下来我们只需要一直进行递归操作直到行列式的阶成为 \(1\) 就好了。所以根据定义我们就可以在 \(O(n!)\) 的时间复杂度内求解出 \(n\) 阶行列式的值了。
优化
假设矩阵 \(A\) 是一个上三角矩阵,那么 \(\operatorname{det}(A)=\prod_{i=1}^{n}a_{i,i}\) 的值,求解的时间复杂度十分优秀为 \(O(n)\),考虑是否可以使用高斯消元进行优化。
排列的性质
- 定义如果 \(\tau(p)\) 为奇数那么 \(p\) 为奇排列,反之即为偶排列。
- 对于一个 \(n(n\geq2)\) 阶排列的所有排列情况,奇排列与偶排列的情况各有 \(\dfrac{1}{2}\cdot n!\) 种。
- 将 \(p\) 中两个不同的元素进行交换得到一个新的排列的过程叫对换操作,进行一次对换操作会改变序列的奇偶性。
矩阵性质
- \(\operatorname{det}(A)=\operatorname{det}(A^T)\),所以说所有的对列成立的性质均对行成立,反之亦然。
带入排列的性质自行观察即可以得到。 - 交换某 \(2\) 行或列,此时的 \(\operatorname{det}(A)\) 需要乘以 \(-1\)。
证明同上。 - 根据上一行进行推论,如果有两行相同那么 \(\operatorname{det}(A)=0\)。
假设 \(s=\operatorname{det}(A)\),不妨设行 \(x\) 与行 \(y\) 相等,那么假设交换 \(x,y\) 则有 \(\operatorname{det}(A)=-s\) 但是矩阵并未变化,所以 \(\operatorname{det}(A)=-\operatorname{det}(A)\) 就得到了 \(\operatorname{det}(A)=0\) 是唯一解了。 - 将 \(A\) 的一行全部乘以 \(k\),那么 \(\operatorname{det}(A)\) 也需要乘以 \(k\)。
考虑从使用定义求解行列式的值的角度进行解释。因为在求值是选择任意行计算的结果都是相同的,所以不妨假设我们刚好选择了全部乘以 \(k\) 的那一行,使用乘法分配律将 \(k\) 提出即可证明。 - 根据上一行进行推论,如果有一行全部为 \(0\) 那么,那么 \(\operatorname{det}(A)=0\)。
假设 \(s=\operatorname{det}(A)\),那么不妨假设 \(x\) 行全部为 \(0\)。将行 \(x\) 全部乘以 \(k\) 得到 \(\operatorname{det}(A)=s\cdot k\),可是矩阵并未变化所以 \(\operatorname{det}(A)=s\),因为 \(k\) 为任意值所以得到 \(\operatorname{det}(A)=0\)。 - 如果行列式对应矩阵 \(A\) 中有一行,是对应 \(2\) 个矩阵 \(B,C\) 中分别的 \(2\) 行所有元素之和,那么有 \(\det(A)=\det(B)+\det(C)\)。
\]
- 将某一行的的 \(k\) 倍加到另外一行,不影响 \(\operatorname{det}(A)\) 的值。
结合前面的一些性质即可证明,十分显然。
高斯消元
考虑到将某一行的的 \(k\) 倍加到另外一行不影响 \(\operatorname{det}(A)\) 的值,可以直接使用高斯消元就可以求解了。同样还是高斯消元,用一个变量记录交换两行引起的符号改变。因为将一行的 \(\) 倍加到另一行上不影响答案,可以采用辗转相除的方式,将其他行的对应位置消成 \(0\)。
因为辗转相除法带一个 \(\log\),所以总的时间复杂度为 \(O(n^2\log W+n^3)\) 也就是 \(O(n^3)\),其中 \(W\) 为矩阵的值域。
AC Code
#define debug
// #define tests
#include<bits/stdc++.h>
#define int long long
#define x first
#define y second
using namespace std;
template<typename T=int> inline T read(){T x;cin>>x;return x;}
struct debug_{template<typename T>debug_&operator<<(T x){
#ifdef debug
cout<<x;
#endif
}}o;
const int N=605;
int n,a[N][N],mod;
void solve(){
cin>>n>>mod;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>a[i][j];
}
}
int flag=1;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
while(a[i][i]){
int s=a[j][i]/a[i][i];
for(int k=i;k<=n;k++){
a[j][k]=(a[j][k]-s*a[i][k]+mod)%mod;
}
flag++;
swap(a[i],a[j]);
}
flag++;
swap(a[i],a[j]);
}
}
int ans=1;
for(int i=1;i<=n;i++){
ans=(ans*a[i][i])%mod;
}
cout<<(ans*(flag%2?1:-1)+mod)%mod;
}
signed main(){
#ifdef debug
#else
ios::sync_with_stdio(false),cin.tie(nullptr);
#endif
int T=1;
#ifdef tests
cin>>T;
#endif
while(T--) solve();
return 0;
}
行列式求值,从 $n!$ 优化到 $n^3$的更多相关文章
- 高斯消元与行列式求值 part1
两道模板题,思路与算法却是相当经典. 先说最开始做的行列式求值,题目大致为给一个10*10的行列式,求其值 具体思路(一开始看到题我的思路): 1.暴算,把每种可能组合试一遍,求逆序数,做相应加减运算 ...
- 洛谷P7112 行列式求值
行列式求值 这是一个让你掉头发的模板题 行列式的定义 行列式 (\(\texttt{Determinant}\)) 是一个函数定义,取值是一个标量. 对一个 \(n\times n\) 的矩阵 \(A ...
- U66785 行列式求值
二更:把更多的行列式有关内容加了进来(%%%%%Jelly Goat奆佬) 题目描述 给你一个N(n≤10n\leq 10n≤10)阶行列式,请计算出它的值 输入输出格式 输入格式: 第一行有一个整数 ...
- 基于上三角变换或基于DFS的行(列)展开的n阶行列式求值算法分析及性能评估
进入大一新学期,看完<线性代数>前几节后,笔者有了用计算机实现行列式运算的想法.这样做的目的,一是巩固自己对相关概念的理解,二是通过独立设计算法练手,三是希望通过图表直观地展现涉及的两种算 ...
- C语言求行列式的值
#include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <window ...
- 延迟求值-如何让Lo-Dash再提速x100?
「注释」作者在本文里没有说明这么一个事实: 目前的版本Lo-Dash v2.4.1并没有引入延迟求值的特性,Lo-Dash 3.0.0-pre中部分方法进行了引入,比如filter(),map(),r ...
- 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值
一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...
- C/C++ 语言中的表达式求值(原文作者:裘宗燕)
经常可以在一些讨论组里看到下面的提问:“谁知道下面C语句给n赋什么值?”m = 1; n = m+++m++;最近有位不相识的朋友发email给我,问为什么在某个C++系统里,下面表达式打印出两个4, ...
- 求值器本质--eval&apply
最近跟着(How to Write a (Lisp) Interpreter (in Python))使用python实现了一个简易的scheme解释器.不得不说使用python这类动态语言实现不要太 ...
- Herding(hdu4709)三点运用行列式求面积
Herding Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
随机推荐
- Centos 8.0 minimal命令行安装图形化界面(超详细)
Centos 8.0 安装图形化界面(超详细) 开始之前呢,请先查看您的Centos版本和是否有root账户权限. 一.安装Centos 图形化界面并重启 下载安装图形化界面 执行命令 yum gro ...
- 在centOS上配置web服务器
centos,web服务,apache,ftp服务器,mysql,makefile (1). 检查系统是否正常 # more /var/log/messages //检查有无系统内核级错误信息 # d ...
- sql 语句系列(计算一个季度的开始日期和结束日期)[八百章之第二十三章]
前言 很多时候,我们进行数据库查询的时候,查询一个季度的财务报表的时候. 比如说查询2020年第一季度的单子,可能传入后台的就是20201,表示的就是20201第一季度,这时候我们要转换为日期. se ...
- jenkins 持续集成和交付 —— 邮箱服务器配置(九)
前言 简介邮箱服务器的配置,让jenkins在构建完成后,能有一个邮箱结果通知到我们,这样就不用每次盯着jenkins 看是否完成了. 正文 1.安装插件 安装下面这个插件. Email Extens ...
- Scratch3之AI集成 - flappy bird AI版本
AI神秘且有趣,我们一个经典的游戏flappy bird集成AI,实现自训练成长的聪明的笨鸟.先上效果: 初始化的笨鸟拥有分身,每个分身都有自我学习功能,根据自己的移动轨迹和得分情况进行汇总,进行新一 ...
- leetcode第 181 场周赛
5364. 按既定顺序创建目标数组 给你两个整数数组 nums 和 index.你需要按照以下规则创建目标数组: 目标数组 target 最初为空. 按从左到右的顺序依次读取 nums[i] 和 in ...
- Java使用ganymed工具包执行LINUX命令教程
了解更多开发技巧,请访问,架构师小跟班官网:https://www.jiagou1216.compackage com.jiagou;import ch.ethz.ssh2.Connection;im ...
- 【笔记】oracle INTERSECT指令&邮箱的正则匹配&trim()函数
[笔记]oracle INTERSECT 和 UNION 指令类似, INTERSECT 也是对两个 SQL 语句所产生的结果做处理的. 不同的地方是, UNION 基本上是一个 OR (如果这个值存 ...
- 1小时打造HaaS版小小蛮驴智能车
简介: 2020年云栖大会上,阿里云发布了一款机器人"小蛮驴",瞬间激起千层浪,无人车,智能物流,机器人等一些概念又火热了一把. 借"小蛮驴"的东风以及火热的H ...
- OpenYurt 联手 eKuiper,解决 IoT 场景下边缘流数据处理难题
简介: 云计算的出现促使物联网实现爆炸式增长.在设备规模和业务复杂度不断攀升的趋势之下,边缘计算因其能够将计算能力更靠近网络边缘和设备,从而带来云性能成本的降低,也在这波浪潮之下得到快速发展. 作者 ...