The definition has terms; Gaussian elimination computes it in .

Computing it

long long determinant(vector<vector<long long>> a, long long MOD) {
    int n = a.size();
    long long det = 1;
    for (int i = 0; i < n; i++) {
        int piv = -1;
        for (int r = i; r < n; r++) if (a[r][i]) { piv = r; break; }
        if (piv < 0) return 0;                            // singular
        if (piv != i) { swap(a[piv], a[i]); det = MOD - det; }   // row swap flips the sign
        det = det * a[i][i] % MOD;
        long long inv = powmod(a[i][i], MOD - 2, MOD);
        for (int r = i + 1; r < n; r++) {
            long long f = a[r][i] * inv % MOD;
            if (!f) continue;
            for (int c = i; c < n; c++)
                a[r][c] = (a[r][c] - f * a[i][c] % MOD + MOD) % MOD;
        }
    }
    return det;
}

Row operations and the determinant:

OperationEffect on
Swap two rowsmultiply by
Multiply a row by multiply by
Add a multiple of one row to anotherunchanged

Only the first two need tracking, which is why elimination works.

Properties

Property
iff is singulariff the rows are linearly dependent
of a triangular matrixproduct of the diagonal
= product of eigenvalues
of a block-triangular matrixproduct of the blocks’ determinants

Over which ring?

SettingMethod
Modulo a primeGaussian elimination with inverses,
Modulo a compositeEuclidean row reduction (repeated subtraction, like gcd) — no inverses needed,
Exact integersBareiss — fraction-free, no coefficient blowup
Exact, hugecompute modulo several primes + CRT, with the Hadamard bound to know when to stop
Floating pointLU decomposition with partial pivoting
SparseWiedemann,

Composite modulus without inverses

for (int r = i + 1; r < n; r++)
    while (a[r][i]) {                            // Euclidean-style
        long long t = a[i][i] / a[r][i];
        for (int c = i; c < n; c++)
            a[i][c] = (a[i][c] - t * a[r][c] % MOD + MOD) % MOD;
        swap(a[i], a[r]); det = MOD - det;
    }

— the standard trick when the modulus is not prime.

Hadamard’s bound

for entries bounded by . Tells you how many CRT primes are needed for an exact answer.

Where determinants appear

ProblemDeterminant
Count spanning treesMatrix-Tree theorem — a Laplacian cofactor
Count Eulerian circuitsBEST theorem (an arborescence count × factorials)
Perfect matching exists (general graph)Tutte matrix rank
Count perfect matchings in a planar graphFKT algorithm — a Pfaffian, hence a determinant
Count perfect matchings in a bipartite graphthe permanentp-hard, no determinant shortcut
Lattice point counting / volumedeterminant of the basis
Orientation testa or determinant
Circle through three pointsa determinant
Solving Cramer’s rule ( — use elimination instead)
Lindström-Gessel-Viennotcount non-intersecting lattice paths

Lindström-Gessel-Viennot is worth flagging: the number of families of non-intersecting paths between two sets of endpoints is a determinant of the pairwise path counts. It turns several hard-looking counting problems into an computation.

Permanent — the hard cousin


— the determinant without signs. Computing it is #P-complete, and the signs are exactly what makes the determinant easy. Best known: Ryser’s formula, , which is bitmask DP in disguise.

See also: Gaussian Elimination · Rank · Matrix-Tree Theorem