UVa 684 - Integral Determinant
Published on 2016-03-15描述
给定一个 阶行列式,请你求行列式的值。
样例输入
2 5 2 3 4 3 2 3 5 1 6 7 4 8 9 0
样例输出
14 -27 *
分析
行列式知识简单提要(建议先有高等代数知识,否则你就默认下面的成立,足够做这个题目了):
若 为 1 ~ n 的一个排列,记 为排列 的逆序对数量。
- 阶行列式的值:若 为 1 ~ n 的所有排列组成的集合,行列式 行 列的元素为 ,则行列式的值为 。
- 交换行列式的任意行(列),行列式的值符号改变。
- 行列式的某一行(列)全部减去行列式的另一行(列)的任意倍,行列式的值不改变。
- 若行列式的某一行(列)全为 0,那么行列式的值为 0。
- 代数余子式:在一个 阶行列式 中,把元素 所在的行与列划去后,剩下的 个元素按照原来的次序组成的一个 阶行列式 ,称为元素 的余子式, 带上符号 称为 的代数余子式,记作 。
- 若行列式的某一行(列)仅有一个数不为 0,为 那么行列式的值为 乘其代数余子式,记作 。
算法:思路很清晰,不断的把行列式降维度。
假设为 阶行列式,先进行列对换,使第一个元素为第一行中最大的元素(为了精度),如果全为 0,那么行列式的值直接就是 0。否则根据减一行的任意倍,值不改变的定理,让第一行除了第一个全为 0,把行列式的值化为 。接着迭代下去即可。
注意到题目说明输出是整数,而且要求使用分数来避免精度问题。我懒得写分数类,直接送上 __float128
128位的浮点数来避免精度,就是时间有点慢。
代码
// Created by Sengxian on 3/15/16. // Copyright (c) 2016年 Sengxian. All rights reserved. // UVa 684 行列式求值 #include <algorithm> #include <iostream> #include <sstream> #include <cctype> #include <cstring> #include <cstdio> #include <cmath> #include <vector> #include <queue> #include <stack> using namespace std; inline int ReadInt() { int n = 0, ch = getchar(); bool flag = false; while (!isdigit(ch)) flag |= ch == '-', ch = getchar(); while (isdigit(ch)) n = (n << 1) + (n << 3) + ch - '0', ch = getchar(); return flag ? -n : n; } typedef long long ll; typedef __float128 type; const type eps = 1e-8; const int maxn = 30 + 3; int n; type a[maxn][maxn]; type myAbs(type a) { return a > 0 ? a : -a; } type solve() { double product = 1.0; bool flag = true; for (int i = 0; i < n; ++i) { int idx = i; for (int j = i; j < n; ++j) if(myAbs(a[i][j]) > myAbs(a[i][idx])) idx = j; if (myAbs(a[i][idx]) < eps) return 0; //一行全为 0 if (idx != i) { flag = !flag; for (int j = i; j < n; ++j) swap(a[j][idx], a[j][i]); } for(int j = i + 1; j < n; ++j) for(int k = n - 1; k >= i; --k) a[k][j] -= a[k][i] / a[i][i] * a[i][j]; product *= a[i][i]; } return flag ? product : -product; } int main() { while (n = ReadInt(), n) { for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) a[i][j] = ReadInt(); printf("%lld\n", (ll)solve()); } puts("*"); return 0; }
附加输入
30 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 3 4 2 1 2 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 9 5 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 2 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 3 0 1 0 0 0 7 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 5 1 2 9 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 7 4 1 0
附加输出
-1725324300 *