洛谷题单指南-基础线性代数-P7112 【模板】行列式求值

原题链接:https://www.luogu.com.cn/problem/P7112

题意解读:行列式求值

解题思路:

1、暴力法:

image

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;
}

 

posted @ 2026-02-28 14:45  hackerchef  阅读(2)  评论(0)    收藏  举报