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;
}Proof: the Catalan formulas, the reflection principle and the cycle lemma
Reflection. Write a path to as a walk (up in the “#up − down” height). A bad walk (one that reaches height ) is reflected after its first visit to : every later step is negated. This is a bijection between bad walks from 0 to 0 and all walks from 0 to (the inverse reflects after the first visit to , which every walk to has), and the latter have ups among steps: . So . The same argument with ups and downs gives
ballot, and with start heightbaland end height 0 givesbracketCompletions(bad walks reach ; reflecting the start across gives start , i.e. ups).Strict ballot. A strictly positive walk starts with an up step and then never drops below height 1: .
Cycle lemma. Let be integers, each , with sum ; then exactly of the rotations have all partial sums positive. Extend the sequence periodically with partial sums (). The rotation starting after position is good iff for all , iff for every (later periods only add ). Because each step rises by at most 1 and as , for every integer the last index with satisfies , and these are exactly the good indices. Since , a window of consecutive indices contains exactly of them. With entries and entries (), each of the sequences has exactly one good rotation, and its rotations are distinct (a sequence with period would have a sum divisible by ). A good rotation starts with and the rest stays and ends at 1, so removing the leading gives a Dyck word: . (The old statement “entries ” is false: has sum 2 but only one good rotation.) The gas station start uses the same “last minimum of the prefix sums” argument.
Recurrence and GF. A non-empty Dyck word splits uniquely as
( A ) Bat the first return to height 0, with , Dyck words: , i.e. ; the root with is . The ratio . The asymptotic follows from divided by . Parity: by Kummer (Binomial Identities) is the number of 1 bits of , and is the number of trailing 1 bits of ; is odd iff these are equal, i.e. iff all bits of are trailing ones: .Bijections. A binary tree maps to
( left ) right; a plane tree to the bracket word of its DFS (open on entering a child, close on leaving); a triangulation of the -gon to a binary tree rooted at the triangle on a fixed edge (the other two sides lead to the left and right sub-polygons); parenthesisations are binary trees with the factors as leaves; full binary trees with leaves are binary trees with internal nodes after deleting the leaves. Chords: label each chord’s first endpoint(and second); non-crossing means every chord encloses a balanced word, and conversely the matching of a bracket word is non-crossing. Non-crossing partitions: the block of 1 leaves gaps (after each ) holding independent non-crossing partitions, so , which simplifies to . 231-avoiding: with at position , every element before must be smaller than every element after it (otherwise with is a 231), and both sides avoid 231: the Catalan recurrence. Reversal and complement map 231 to 132, 213 and 312; the class is also counted by (Simion–Schmidt bijection). A permutation is stack-sortable iff it avoids 231 (Knuth). Tableaux: reading , write(for an entry in the top row and)for the bottom row; the column condition is exactly the ballot condition. Coins: rotating by , a stack with bottom coins is the set of cells under a Dyck path of semilength .
kthBalanced.d[r][b]counts walks of length from height to 0 staying ; at each position, the number of valid sequences that continue with(isd[r][bal+1], so the lexicographic choice compares with it. Checked against brute force over all bracket sequences for .
Lattice paths with boundaries and obstacles
| Constraint | Count |
|---|---|
| , 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, unrestricted | Delannoy |
| steps E, N, NE below the diagonal | large 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 peaks | Narayana , |
| -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: CatalanComplexity: 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.
Proof: boundaries, obstacles, Fuss–Catalan and Narayana
One boundary. A path that touches is reflected across that line from its first touch on; the end maps to , and the map is a bijection onto all paths to that point, which number .
Two boundaries (André). In the walk picture the height starts at 0 and ends at after steps of ; counts unrestricted walks ending at . Let = touching , = touching . Classify a bad walk by its sequence of boundary touches, compressed to alternating letters (). The walks whose compressed sequence contains a given alternating word as a subsequence are counted by reflecting the end point successively across the boundaries in (each reflection is a bijection, as in the one-boundary case), which yields at a translate (even length) or / (odd length). Inclusion–exclusion over these words, with sign , counts every bad walk exactly 0 times net, and regrouping the terms gives the stated sum. Terms vanish once , so only values of contribute.
Obstacles. Sorting cells lexicographically is a linear extension of the dominance order, so every cell that a path to
bl[i]can visit before it has a smaller index. A path tobl[i]that hits blocked cells has a unique first one,bl[j], and is a path tobl[j]avoiding earlier cells ( choices) followed by any path tobl[i]: subtracting gives . The target is appended last; if it or the start is blocked, the subtraction removes everything.Fuss–Catalan. Encode a -ary tree with internal nodes in preorder, internal node , leaf (there are leaves): proper prefixes have sum and the total is . Reversing and negating gives entries in , all , sum 1, with all prefix sums positive, and every such sequence arises from exactly one tree. By the cycle lemma each of the arrangements has exactly one good rotation and distinct rotations: .
Narayana. Take the words with letters U and letters D and count cyclic UD factors (the number of cyclic runs of U). Pairs (word, distinguished run) correspond bijectively to (shift, word starting with U and ending with D with runs of each letter), so . Each word has exactly one good rotation U, a Dyck word, and its cyclic UD count equals the peak count of (the final D of is followed by the leading U, which is a DU). Dividing by the rotations: .
Delannoy. Choosing which of the steps are diagonal gives . For the other form, compare generating functions: the step set gives , and with , . Schröder, Motzkin: first-return decompositions as for Catalan; recurrences and proofs are in Stirling, Bell and Partitions. All functions were checked against exhaustive enumeration of paths for small sizes.
Related notes
- Stirling, Bell and Partitions (Eulerian, Motzkin, Schröder, Delannoy tables)
- Generating Functions
- Ballot Problem
- DP Foundations (grid paths)