行列式求值,从 $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 ...
随机推荐
- 安装 php_mongodb.dll的坑
背景 php_mongodb.dll在这里介绍的是for php,php_mongodb.dll是这个坑,因为php_mongodb.dll前生是php_mongo.dll,而这个东西,它又不更新了, ...
- nohup训练pytorch模型时的报错以及tmux的简单使用
问题: 在使用nohup命令后台训练pytorch模型时,关闭ssh窗口,有时会遇到下面报错: WARNING:torch.distributed.elastic.agent.server.api:R ...
- kkfileview搭建实战
kkfileview可以与nginx搭建的文件服务器配合实现预览工作,也可以通过自身的文件系统机制免搭建nginx文件服务器来实现预览工作. nginx 创建nginx # 创建初始容器,获得容器内部 ...
- 深度 | 从DevOps到BizDevOps, 研发效能提升的系统方法
简介:研发效能提升不知从何下手.一头雾水?阿里资深技术专家一文为你揭秘研发效能提升的系统方法. 注:本文是对云栖大会何勉分享内容的整理 这几年"研发效能"一直是热词,很多组织 ...
- Flink+Hologres亿级用户实时UV精确去重最佳实践
简介: Flink+Hologres亿级用户实时UV精确去重最佳实践 UV.PV计算,因为业务需求不同,通常会分为两种场景: 离线计算场景:以T+1为主,计算历史数据 实时计算场景:实时计算日常新增的 ...
- 当微服务遇上 Serverless | 微服务容器化最短路径,微服务 on Serverless 最佳实践
简介: 阿里云Serverless应用引擎(SAE)初衷是让客户不改任何代码,不改变应用部署方式,就可以享受到微服务+K8s+Serverless的完整体验,开箱即用免运维. 前言 微服务作为一种更 ...
- 修复 WPF 安装 WindowsAppSDK 库构建失败 NETSDK1082 和 NETSDK1112 找不到 win10-arm 失败
通过在 WPF 项目上安装 WindowsAppSDK 库,可以让 WPF 使用上 Win10 及以上版本提供的 Windows Runtime 强大的 API 集和使用上更多的黑科技.本文记录在安装 ...
- Etcd 可视化管理工具,GUI 客户端。
Etcd Assistant--Etcd 可视化管理工具,GUI 客户端. 下载地址:http://www.redisant.cn/etcd 主要功能: 支持多标签页,同时连接到多个集群 以漂亮的格式 ...
- ESP32 使用LVGL案例
一.完成LVGL移植 在使用LVGL提供的测试案例时,需要先移植LVGL,不明白的小伙伴看我之前的笔记 esp-idf 移植 lvgl8.3.3. 移植完成后的项目文件如下图所示 二.添加需要的测试案 ...
- 第一讲 Cadence-于真博士课程简介
第一讲 Cadence-于真博士课程简介 以工程化的思想来学习本课程,比较有效,从一个DSP开发板设计为例开始,做出PCB板,顺带学会Cadence软件操作,而不是仅仅学习软件. 前期准备工作,阅读配 ...