Permutations

Combinations

Also written .

Pascal’s identity:

Basis of Pascal’s triangle; gives an DP for binomial coefficients without factorials or modular inverses.

Identities:

Binomial Theorem

Computing nCr Fast, Modulo a Prime

For up to : precompute factorials and inverse factorials mod , then answer each query in . (See Modular Arithmetic for the standalone modinv / modpow building blocks.)

Code — Factorial / Inverse-Factorial Precomputation

#include <bits/stdc++.h>
using namespace std;
 
static const long long MOD = 1000000007;
static const int MAXN = 1000000;
 
long long fact[MAXN + 1], invfact[MAXN + 1];
 
long long modpow(long long a, long long b, long long mod) {
    long long res = 1;
    a %= mod;
    while (b > 0) {
        if (b & 1) res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}
 
void precompute() {
    fact[0] = 1;
    for (int i = 1; i <= MAXN; i++)
        fact[i] = fact[i - 1] * i % MOD;
 
    invfact[MAXN] = modpow(fact[MAXN], MOD - 2, MOD);
    for (int i = MAXN; i > 0; i--)
        invfact[i - 1] = invfact[i] * i % MOD;
}
 
long long nCr(int n, int r) {
    if (r < 0 || r > n) return 0;
    return fact[n] * invfact[r] % MOD * invfact[n - r] % MOD;
}

Code — Pascal’s-Triangle DP (Small n, No Modular Inverse Needed)

vector<vector<long long>> pascal(int n, long long mod) {
    vector<vector<long long>> C(n + 1, vector<long long>(n + 1, 0));
    for (int i = 0; i <= n; i++) {
        C[i][0] = 1;
        for (int j = 1; j <= i; j++)
            C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
    }
    return C;
}

Catalan Numbers

Catalan numbers count balanced parenthesizations, binary trees with internal nodes, Dyck paths, and polygon triangulations, among many other structures.

long long catalan(int n, long long mod) {
    // requires precompute() from the nCr section above
    return ((nCr(2 * n, n) - nCr(2 * n, n + 1)) % mod + mod) % mod;
}

Time Complexity: per query (given precomputed factorials), precompute

Stars and Bars

Number of ways to distribute identical items into distinguishable bins.

Empty bins allowed:

Each bin non-empty:

long long distributeItems(int n, int k, bool allowEmpty) {
    if (allowEmpty) return nCr(n + k - 1, k - 1);
    return nCr(n - 1, k - 1); // n must be >= k
}

Inclusion-Exclusion Principle

Standard applications: counting numbers divisible by at least one of a set of primes, counting surjective functions, Euler’s totient (see General), and derangements (below).

// counts integers in [1, N] divisible by at least one of the given primes
long long countDivisibleByAny(long long N, vector<long long> &primes) {
    int k = primes.size();
    long long total = 0;
    for (int mask = 1; mask < (1 << k); mask++) {
        long long lcm = 1;
        int bits = __builtin_popcount(mask);
        bool overflow = false;
        for (int i = 0; i < k; i++) {
            if (mask & (1 << i)) {
                long long g = __gcd(lcm, primes[i]);
                if (lcm / g > N / primes[i]) { overflow = true; break; }
                lcm = lcm / g * primes[i];
            }
        }
        if (overflow) continue;
        long long term = N / lcm;
        total += (bits % 2 == 1) ? term : -term;
    }
    return total;
}

Time Complexity: for sets

Derangements

Permutations of elements with no fixed points.

long long derangements(int n, long long mod) {
    vector<long long> D(n + 1);
    D[0] = 1;
    if (n >= 1) D[1] = 0;
    for (int i = 2; i <= n; i++)
        D[i] = (i - 1) * ((D[i - 1] + D[i - 2]) % mod) % mod;
    return D[n];
}

Time Complexity:

Burnside’s Lemma

Counts the number of distinct objects up to the symmetry of a group acting on a set :

where is the set of elements of fixed by .

Classic example — necklaces: count distinct necklaces of beads and colors under rotation. A rotation by positions decomposes the beads into cycles, and a coloring is fixed by that rotation iff it’s constant on every cycle — giving fixed colorings.

long long distinctNecklaces(int n, int k, long long mod) {
    long long total = 0;
    for (int d = 0; d < n; d++) {
        int g = __gcd(n, d);
        total = (total + modpow(k, g, mod)) % mod;
    }
    return total * modinv(n, mod) % mod; // modinv from Modular Arithmetic
}

Time Complexity:

Pólya Enumeration Theorem

A restatement of Burnside’s Lemma specialized to coloring problems: since a coloring is fixed by exactly when it’s constant on every cycle of , where is the number of cycles in ‘s permutation of the underlying positions. This gives

The necklace-counting code above is already an instance of PET: rotation by decomposes positions into cycles. PET becomes essential (over plain Burnside) once the group includes more complex symmetries (e.g. reflections, or automorphisms of a graph), where must be computed from the specific permutation structure of each rather than a simple .

Generating Functions

Ordinary Generating Function (OGF) of a sequence :

Sequence operations become algebraic operations on the generating function: shifting the sequence corresponds to multiplying by , and convolution () corresponds to multiplying the two generating functions, .

Examples:

Exponential Generating Function (EGF), used for labeled structures:

Example: the EGF for permutations of labeled items is ; the EGF for derangements is .

In competitive programming, generating functions are mainly wielded through polynomial multiplication (convolution), often accelerated with NTT (see the 998244353 modulus in Modular Arithmetic), to compute an entire sequence’s terms in bulk rather than one value at a time.

Stirling Numbers

First kind — number of permutations of elements with exactly cycles:

Second kind — number of ways to partition a set of labeled elements into exactly non-empty subsets:

vector<vector<long long>> stirlingSecondKind(int n, long long mod) {
    vector<vector<long long>> S(n + 1, vector<long long>(n + 1, 0));
    S[0][0] = 1;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= i; j++)
            S[i][j] = (S[i - 1][j - 1] + 1LL * j * S[i - 1][j]) % mod;
    return S;
}

Time Complexity:

Bell Numbers

Total number of ways to partition a set of labeled elements into any number of non-empty subsets:

Computed directly with the Bell triangle, avoiding the need to build the full Stirling table:

vector<long long> bellNumbers(int n, long long mod) {
    vector<vector<long long>> tri(n + 1);
    tri[0] = {1};
    vector<long long> B(n + 1);
    B[0] = 1;
    for (int i = 1; i <= n; i++) {
        tri[i].assign(i + 1, 0);
        tri[i][0] = tri[i - 1][i - 1];
        for (int j = 1; j <= i; j++)
            tri[i][j] = (tri[i][j - 1] + tri[i - 1][j - 1]) % mod;
        B[i] = tri[i][0];
    }
    return B;
}

Time Complexity:

Partition Numbers

The integer partition function counts the number of ways to write as a sum of positive integers, ignoring order.

Computed with a coin-change-style DP that builds every value up to using parts :

vector<long long> partitionNumbers(int n, long long mod) {
    vector<long long> p(n + 1, 0);
    p[0] = 1;
    for (int part = 1; part <= n; part++)
        for (int i = part; i <= n; i++)
            p[i] = (p[i] + p[i - part]) % mod;
    return p;
}

Time Complexity:
Space Complexity:

Recurrence Relations

A linear homogeneous recurrence with constant coefficients has the form

Its behavior is governed by the characteristic equation

whose roots give the closed form (for distinct roots), with the fixed by the initial conditions.

For competitive programming, the practical takeaway is that any such recurrence can be evaluated for huge in by encoding one step of the recurrence as a transition matrix and applying Matrix Exponentiation. For example, Fibonacci’s becomes

Pigeonhole Principle

Naive form. If more than objects are placed into boxes, at least one box contains more than one object.

General form. If pigeons are placed into holes, at least one hole contains at least pigeons.

Generalized form. If more than objects are placed into boxes, at least one box contains more than objects.

Application is usually a two-step process: identify what the “pigeons” and “holes” are, then finish with problem-specific reasoning once the principle guarantees a collision.