Catalan Number Variants
The n -th Catalan number is C_n = (1)/(n+1)C(2n, n). Find sum_(k=0)^1000 C_k (mod 10^9+7).
Problem Statement
This archive keeps the full statement, math, and original media on the page.
This problem is based on (but not identical to) the scoring for the card game
Consider a normal pack of \(52\) cards. A Hand is a selection of one or more of these cards.
For each Hand the
The
-
Pairs. A pair is two cards of the same rank. Every pair is worth \(2\) points.
-
Runs. A run is a set of at least \(3\) cards whose ranks are consecutive, e.g. 9, 10, Jack. Note that Ace is never high, so Queen, King, Ace is not a valid run. The number of points for each run is the size of the run. All locally maximum runs are counted. For example, 2, 3, 4, 5, 7, 8, 9 the two runs of 2, 3, 4, 5 and 7, 8, 9 are counted but not 2, 3, 4 or 3, 4, 5.
-
Fifteens. A fifteen is a combination of cards that has value adding to \(15\). Every fifteen is worth \(2\) points. For this purpose the value of the cards is the same as in the Hand Score.
For example, \((5 \spadesuit , 5 \clubsuit , 5 \diamondsuit , K \heartsuit )\) has a Cribbage score of \(14\) as there are four ways that fifteen can be made and also three pairs can be made.
The example \(( A \diamondsuit , A \heartsuit , 2 \clubsuit , 3 \heartsuit , 4 \clubsuit , 5 \spadesuit )\) has a Cribbage score of \(16\): two runs of five worth \(10\) points, two ways of getting fifteen worth \(4\) points and one pair worth \(2\) points. In this example the Hand score is equal to the Cribbage score.
Find the number of Hands in a normal pack of cards where the Hand score is equal to the Cribbage score.
Problem 928: Catalan Number Variants
Mathematical Foundation
Theorem 1 (Ratio Recurrence). The Catalan numbers satisfy and
Proof. Compute the ratio directly:
Simplifying: .
Theorem 2 (Segner Convolution Recurrence). For all :
Proof. Consider Dyck paths from to . Each such path first touches the -axis at some step (the first return). The path decomposes as: an up-step, a Dyck path of semilength (shifted up by 1), a down-step, and a Dyck path of semilength . Since the first part has choices and the second has choices, summing over all first-return times gives the recurrence.
Theorem 3 (Generating Function). The ordinary generating function satisfies the functional equation , with explicit solution
Proof. Theorem 2 states , which means . Multiplying by : , i.e., . Solving this quadratic in :
The minus sign is chosen to ensure (by L’Hopital or series expansion).
Theorem 4 (Asymptotic Growth). As :
Proof. Using Stirling’s approximation :
Lemma 1 (Modular Inverse via Fermat). For prime and : .
Proof. By Fermat’s little theorem, , so .
Editorial
Alternative (precompute factorials). We method 1: Using ratio recurrence with modular inverses. We enumerate the admissible parameter range, discard candidates that violate the derived bounds or arithmetic constraints, and update the final set or total whenever a candidate passes the acceptance test.
Pseudocode
Method 1: Using ratio recurrence with modular inverses
C_{n+1} = C_n * 2*(2n+1) * inverse(n+2) mod MOD
Precompute factorials and inverse factorials mod MOD
C_k = fact[2k] * inv_fact[k+1] * inv_fact[k] mod MOD
Complexity Analysis
- Time (ratio recurrence): , where each step requires one modular inverse via binary exponentiation in .
- Time (factorial precomputation): . Precomputing factorials is ; a single modular inverse costs ; the remaining inverse factorials are via backward recurrence.
- Space: for the ratio method; for the factorial method.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
/*
* Problem 928: Catalan Number Variants
*
* Find sum_{k=0}^{1000} C_k mod 10^9+7.
* C_n = (2n)! / ((n+1)! * n!).
*
* Recurrence: C_{k+1} = C_k * 2(2k+1) / (k+2).
* Or use factorial precomputation with modular inverses.
*
* Generating function: C(x) = (1 - sqrt(1-4x)) / (2x).
* Asymptotics: C_n ~ 4^n / (n^{3/2} sqrt(pi)).
*
* Complexity: O(N) with factorial precomputation.
*/
long long MOD = 1000000007;
long long power(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;
}
int main() {
int N = 1000;
vector<long long> fact(2*N + 2), inv_fact(2*N + 2);
fact[0] = 1;
for (int i = 1; i <= 2*N + 1; i++)
fact[i] = fact[i-1] * i % MOD;
inv_fact[2*N+1] = power(fact[2*N+1], MOD-2, MOD);
for (int i = 2*N; i >= 0; i--)
inv_fact[i] = inv_fact[i+1] * (i+1) % MOD;
long long total = 0;
for (int k = 0; k <= N; k++) {
// C_k = (2k)! / (k! * (k+1)!)
long long c = fact[2*k] % MOD * inv_fact[k] % MOD * inv_fact[k+1] % MOD;
total = (total + c) % MOD;
}
cout << total << endl;
// Verify first Catalan numbers: 1, 1, 2, 5, 14, 42
auto catalan = [&](int k) {
return fact[2*k] % MOD * inv_fact[k] % MOD * inv_fact[k+1] % MOD;
};
assert(catalan(0) == 1);
assert(catalan(1) == 1);
assert(catalan(2) == 2);
assert(catalan(3) == 5);
assert(catalan(4) == 14);
return 0;
}
"""
Problem 928: Catalan Number Variants
Compute the sum of Catalan numbers C_0 + C_1 + ... + C_N modulo 10^9+7.
Uses modular arithmetic with precomputed factorials and inverse factorials.
Key ideas:
- Catalan number: C_n = C(2n, n) / (n+1) = (2n)! / (n! * (n+1)!).
- Recurrence: C_{n+1} = C_n * 2(2n+1) / (n+2).
- Asymptotic: C_n ~ 4^n / (n^{3/2} * sqrt(pi)).
- Generating function: C(x) = (1 - sqrt(1-4x)) / (2x).
Methods:
1. Modular arithmetic with factorial precomputation
2. Recurrence relation (exact integers for small n)
3. Asymptotic approximation comparison
4. Ratio analysis C_{n+1}/C_n approaching 4
"""
import numpy as np
def solve(N=1000):
"""Compute sum of C_0..C_N mod 10^9+7."""
MOD = 10**9 + 7
fact = [1] * (2 * N + 2)
for i in range(1, 2 * N + 2):
fact[i] = fact[i - 1] * i % MOD
inv_fact = [1] * (2 * N + 2)
inv_fact[2 * N + 1] = pow(fact[2 * N + 1], MOD - 2, MOD)
for i in range(2 * N, -1, -1):
inv_fact[i] = inv_fact[i + 1] * (i + 1) % MOD
def catalan_mod(k):
return fact[2 * k] * inv_fact[k] % MOD * inv_fact[k + 1] % MOD
total = 0
for k in range(N + 1):
total = (total + catalan_mod(k)) % MOD
return total
def catalan_exact(N):
"""Compute exact Catalan numbers C_0..C_N using the recurrence."""
cats = [1]
for k in range(1, N + 1):
cats.append(cats[-1] * 2 * (2 * k - 1) // (k + 1))
return cats
def catalan_asymptotic(n):
"""Asymptotic estimate: C_n ~ 4^n / (n^{3/2} * sqrt(pi))."""
if n == 0:
return 1.0
return 4**n / (n**1.5 * np.sqrt(np.pi))
def catalan_ratios(cats):
"""Compute C_{n+1}/C_n for each n. Approaches 4."""
return [cats[i + 1] / cats[i] for i in range(len(cats) - 1)]
# Solve and verify
answer = solve()
# Verify exact Catalan numbers against known values
cats = catalan_exact(20)
known = [1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796]
for i, val in enumerate(known):
assert cats[i] == val, f"Catalan({i}) mismatch: {cats[i]} != {val}"
# Verify formula: C_n = C(2n,n)/(n+1)
from math import comb
for n in range(15):
assert cats[n] == comb(2 * n, n) // (n + 1), f"Binomial formula mismatch at {n}"
# Verify sum of first few
assert sum(cats[:5]) == 1 + 1 + 2 + 5 + 14 # = 23
print(answer)