Catalan numbers, the reflection principle behind them, its generalisations (ballot problem, shifted and double boundaries, paths around obstacles) and the relatives (Narayana, Motzkin, Schröder, Fuss–Catalan). Binomials come from Comb in Modular Arithmetic; Stirling, Bell and the other special sequences are in Stirling, Bell and Partitions, derangements and surjections in Inclusion–Exclusion.



Asymptotically ; is odd iff .

Object of size (all in bijection)Count
balanced bracket sequences / Dyck words of length
mountain ranges with up and down strokes; monotone paths not crossing the diagonal
binary trees with internal nodes; full binary trees with leaves
rooted plane (ordered) trees with vertices
ways to parenthesise a product of factors
triangulations of a convex -gon
non-crossing chord diagrams (perfect matchings) on points of a circle; non-crossing partitions of
permutations of avoiding any one fixed 3-pattern (e.g. 231); stack-sortable permutations
standard Young tableaux of shape
ways to stack coins with coins in the bottom row (each upper coin on two below)

Recognising one tells you the answer to all: compute 6 terms by brute force and compare with 1, 1, 2, 5, 14, 42. When an unfamiliar sequence appears, search OEIS with the first 6–8 terms: it usually names the sequence and gives a recurrence or closed form (a legitimate contest technique).

mint catalan(int n, const Comb& cb) { return cb.C(2 * n, n) * cb.iv[n + 1]; }   // cb covers 2n
 
mint ballot(ll a, ll b, const Comb& cb) {                 // a ups, b downs, every prefix #up >= #down (a >= b)
    if (b > a) return 0;
    return cb.C(a + b, a) - cb.C(a + b, a + 1);
}
 
mint ballotStrict(ll a, ll b, const Comb& cb) {           // every non-empty prefix #up > #down: (a-b)/(a+b) C(a+b, a)
    if (a + b == 0) return 1;
    if (b >= a) return 0;
    return mint(a - b) * cb.C(a + b, a) / mint(a + b);
}
 
mint bracketCompletions(int r, int bal, const Comb& cb) { // ways to append r brackets to a prefix of balance bal >= 0
    if (bal < 0 || (r - bal) % 2 || bal > r) return 0;
    int up = (r - bal) / 2;
    return cb.C(r, up) - (up ? cb.C(r, up - 1) : mint(0));
}
 
string kthBalanced(int n, ll k) {                         // 0-indexed k-th balanced sequence of length 2n, '(' < ')', n <= 30
    vector<vector<ll>> d(2 * n + 1, vector<ll>(2 * n + 2, 0)); d[0][0] = 1;   // d[r][b]: completions of length r from balance b
    for (int r = 1; r <= 2 * n; r++) for (int b = 0; b <= 2 * n; b++) d[r][b] = d[r - 1][b + 1] + (b ? d[r - 1][b - 1] : 0);
    string s; int bal = 0;
    for (int i = 0; i < 2 * n; i++) {
        int r = 2 * n - i - 1;
        if (d[r][bal + 1] > k) s += '(', bal++;
        else k -= d[r][bal + 1], s += ')', bal--;
    }
    return s;
}

Lattice paths with boundaries and obstacles

ConstraintCount
, steps right and up
never above (), end below it (reflect across )
strictly between two diagonals with , (André, repeated reflections)
Dyck paths of height two-boundary formula with , ; also for
avoiding blocked cells inclusion–exclusion over the first blocked cell hit (CF 559C)
steps E, N, NE, unrestrictedDelannoy
steps E, N, NE below the diagonallarge Schröder: 1, 2, 6, 22, 90, 394
up / down / flat steps staying Motzkin: 1, 1, 2, 4, 9, 21, 51, 127
Dyck paths with peaksNarayana ,
-ary trees with internal nodes; walks with steps , Fuss–Catalan
mint pathsAvoiding(int R, int C, vector<pair<int, int>> bl, const Comb& cb) {   // (0,0) -> (R,C), steps +row / +col, O(k^2)
    sort(all(bl)); bl.erase(unique(all(bl)), bl.end()); bl.push_back({R, C});
    auto g = [&](int dr, int dc) -> mint { return dr < 0 || dc < 0 ? mint(0) : cb.C(dr + dc, dr); };
    int k = sz(bl); vector<mint> f(k);                     // f[i]: paths to bl[i] avoiding every earlier blocked cell
    for (int i = 0; i < k; i++) {
        f[i] = g(bl[i].first, bl[i].second);
        for (int j = 0; j < i; j++) f[i] -= f[j] * g(bl[i].first - bl[j].first, bl[i].second - bl[j].second);
    }
    return f[k - 1];                                       // 0 if the start or the target is blocked
}
 
mint pathsBetweenLines(int n, int m, int lo, int hi, const Comb& cb) {   // n steps +x, m steps +y, lo < y - x < hi throughout (lo < 0 < hi)
    int N = n + m, t = m - n, d = hi - lo;
    if (!(lo < t && t < hi)) return 0;
    auto W = [&](ll e) -> mint { if (e < -N || e > N || (N + e) % 2) return 0; return cb.C(N, (int)((N + e) / 2)); };
    mint res = 0;
    for (ll k = -(N / d) - 2; k <= N / d + 2; k++) res += W(t + 2 * k * d) - W(2LL * hi - t + 2 * k * d);
    return res;
}
 
mint fussCatalan(int n, int k, const Comb& cb) { return cb.C(k * n, n) / mint((ll)(k - 1) * n + 1); }   // k = 2: Catalan

Complexity: pathsAvoiding after factorials up to ; pathsBetweenLines ; the others . Notes on computing modulo a prime: the needs an inverse (cb.iv); keep alternating signs as mint subtraction; the convolution recurrence is only needed for variants (it becomes with FFT or online convolution when the recurrence is modified); a whole row of Stirling numbers is one convolution.