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
| Algorithm | Exponent |
|---|---|
| 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
| Task | Method | Cost |
|---|---|---|
| Solve | Gaussian elimination | |
| Determinant | Gaussian elimination | |
| Exact integer determinant | Bareiss | |
| Rank | row reduce, count pivots | |
| Inverse | Gauss-Jordan on | |
| Characteristic polynomial | Faddeev-LeVerrier or Hessenberg | / |
| binary exponentiation | ||
| Sparse system | Wiedemann / Lanczos | |
| Count spanning trees | Matrix-Tree | |
| Perfect matching exists | Tutte 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