Basics

. Defined when is and is ; the result is .

  • Associative but not commutative: in general.
  • Identity with .
  • , .

Fast multiplication in practice

using Mat = vector<vector<long long>>;
const long long MOD = 1e9 + 7;
 
Mat mul(const Mat& a, const Mat& b) {
    int n = a.size(), m = b[0].size(), K = b.size();
    Mat c(n, vector<long long>(m, 0));
    for (int i = 0; i < n; i++)
        for (int k = 0; k < K; k++) {
            if (!a[i][k]) continue;                    // skip zeros
            long long aik = a[i][k];
            for (int j = 0; j < m; j++)
                c[i][j] = (c[i][j] + aik * b[k][j]) % MOD;
        }
    return c;
}

The loop order is the important detail: the inner loop then walks b[k] and c[i] sequentially, so both are cache-friendly. The naive order strides down a column of b and is 3-5× slower.

Further speedups: delay the modulo (accumulate in __int128 or use unsigned long long and reduce every 18 additions), and flatten to a 1D array.

Matrix exponentiation

in by binary exponentiation. This is how linear recurrences, walk counting, and Markov chains get from to . See Matrix Exponentiation and Matrix Exponentiation on DP.

Semirings — the underrated generalisation

Matrix multiplication works over any semiring (an addition-like and a multiplication-like operation, with distributivity). Replacing changes what the product computes:

Semiring computes
number of walks of length from to
shortest path using exactly edges
longest path with exactly edges
reachability in exactly steps
bottleneck (widest) path
parity of walk counts
// min-plus: shortest path with exactly n edges
c[i][j] = min(c[i][j], a[i][k] + b[k][j]);

The min-plus version with binary exponentiation solves “cheapest route using exactly flights” for up to in — a problem with no other reasonable approach.

Fast matrix multiplication

AlgorithmExponent
Schoolbook
Strassen
Coppersmith-Winograd and successors
Lower bound

Strassen computes a block product with 7 multiplications instead of 8 — the same “trade multiplications for additions” idea as Karatsuba. It becomes worthwhile around and is numerically less stable. The sub-2.8 algorithms are galactic.

For boolean matrices, a bitset gives with a tiny constant — better than Strassen for every practical size. See Bitset Optimization.

What matrices compute

TaskMethodCost
Solve Gaussian elimination
DeterminantGaussian elimination
Exact integer determinantBareiss
Rankrow reduce, count pivots
InverseGauss-Jordan on
Characteristic polynomialFaddeev-LeVerrier or Hessenberg /
binary exponentiation
Sparse systemWiedemann / Lanczos
Count spanning treesMatrix-Tree
Perfect matching existsTutte matrix + rank randomized

Working modulo a prime

Everything above works over : replace division by multiplication with the modular inverse. Over a composite modulus, division may be impossible — use a Euclidean-style row reduction (repeatedly subtract multiples, as in the gcd algorithm) instead of pivoting by inverses.

See also: Matrix Exponentiation · Determinant · Gaussian Elimination