洛谷题单指南-基础线性代数-P7112 【模板】行列式求值
原题链接:https://www.luogu.com.cn/problem/P7112
题意解读:行列式求值
解题思路:
1、暴力法:

p是1-n的一个排列, 为一个排列 的逆序对个数,时间复杂度为O(n*n!)
2、矩阵变换
将矩阵变换为上三角矩阵(高斯消元法),行列式的值为对角线元素之积。
矩阵初等变化对于行列式值的影响:
- 交换两行,行列式值符号相反
- 一行乘一个数,行列式值夜乘一个数
- 一行加上另一行的若干倍,行列式值不变
注意:
- 由于常规的高斯消元是把对角线元素变成1,而求行列式由于精度问题没有必要变成1,因为会出现小数,而且要整行乘
- 枚举对角线,然后取该行与其下所有行进行辗转相减,即可进行消元
100分代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 605;
LL n, p;
LL a[N][N];
LL ans = 1, sign = 1;
int main()
{
cin >> n >> p;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
{
cin >> a[i][j];
a[i][j] %= p; // 模p处理
}
// 高斯消元法计算行列式
for(int i = 1; i <= n; i++)
{
// 消除下面所有行的第i列
for(int j = i + 1; j <= n; j++)
{
if(a[i][i] == 0) //如果对角线元素是0,不能用此去消元,直接把要消的行交换即可
{
swap(a[i], a[j]);
sign = -sign;
continue;
}
// 辗转相减法:减到a[j][i]为0为止
while(a[j][i] != 0)
{
// 保证a[i][i]的绝对值 <= a[j][i]的绝对值
if(abs(a[i][i]) > abs(a[j][i]))
{
swap(a[i], a[j]);
sign = -sign; // 交换两行,符号改变
}
// 倍数减法
LL times = a[j][i] / a[i][i];
for(int k = i; k <= n; k++)
a[j][k] = ((a[j][k] - times * a[i][k]) % p + p) % p;
}
}
}
for(int i = 1; i <= n; i++) ans = ans * a[i][i] % p;
ans = (ans * sign % p + p) % p;
cout << ans << endl;
return 0;
}
浙公网安备 33010602011771号