Lambda Count
Let Lambda(n) count the number of permutations of {1, 2,..., n} that consist of exactly two disjoint cycles. Compute Lambda(n) mod p for given n and prime modulus p.
Problem Statement
This archive keeps the full statement, math, and original media on the page.
The lambda-calculus is a universal model of computation at the core of functional programming languages. It is based on lambda-terms, a minimal programming language featuring only function definitions, function calls and variables. Lambda-terms are built according to the following rules:
Any variable $x$ (single letter, from some infinite alphabet) is a lambda-term.
If $M$ and $N$ are lambda-terms, then $(M N)$ is a lambda-term, called the application of $M$ to $N$.
If $x$ is a variable and $M$ is a term, then $(\lambda x. M)$ is a lambda-term, called an abstraction. An abstraction defines an anonymous function, taking $x$ as parameter and sending back $M$.
A lambda-term $T$ is said to be closed if for all variables $x$, all occurrences of $x$ within $T$ are contained within some abstraction $(\lambda x. M)$ in $T$. The smallest such abstraction is said to bind the occurrence of the variable $x$. In other words, a lambda-term is closed if all its variables are bound to parameters of enclosing functions definitions. For example, the term $(\lambda x. x)$ is closed, while the term $(\lambda x. (x y))$ is not because $y$ is not bound.
Also, we can rename variables as long as no binding abstraction changes. This means that $(\lambda x. x)$ and $(\lambda y. y)$ should be considered equivalent since we merely renamed a parameter. Two terms equivalent modulo such renaming are called -equivalent. Note that $(\lambda x. (\lambda y. (x y)))$ and $(\lambda x. (\lambda x. (x x)))$ are not $\alpha$-equivalent, since the abstraction binding the first variable was the outer one and becomes the inner one. However, $(\lambda x. (\lambda y. (x y)))$ and $(\lambda y. (\lambda x. (y x)))$ are $\alpha$-equivalent.
The following table regroups the lambda-terms that can be written with at most $15$ symbols, symbols being parenthesis, $\lambda$, dot and variables.
\[ \begin{array}{|c|c|c|c|} \hline (\lambda x.x) & (\lambda x.(x x)) & (\lambda x.(\lambda y.x)) & (\lambda x.(\lambda y.y)) \\ \hline (\lambda x.(x (x x))) & (\lambda x.((x x) x)) & (\lambda x.(\lambda y.(x x))) & (\lambda x.(\lambda y.(x y))) \\ \hline (\lambda x.(\lambda y.(y x))) & (\lambda x.(\lambda y.(y y))) & (\lambda x.(x (\lambda y.x))) & (\lambda x.(x (\lambda y.y))) \\ \hline (\lambda x.((\lambda y.x) x)) & (\lambda x.((\lambda y.y) x)) & ((\lambda x.x) (\lambda x.x)) & (\lambda x.(x (x (x x)))) \\ \hline (\lambda x.(x ((x x) x))) & (\lambda x.((x x) (x x))) & (\lambda x.((x (x x)) x)) & (\lambda x.(((x x) x) x)) \\ \hline \end{array} \]
Let be $\Lambda(n)$ the number of distinct closed lambda-terms that can be written using at most $n$ symbols, where terms that are $\alpha$-equivalent to one another should be counted only once. You are given that $\Lambda(6) = 1$, $\Lambda(9) = 2$, $\Lambda(15) = 20$ and $\Lambda(35) = 3166438$.
Find $\Lambda(2000)$. Give the answer modulo $1\,000\,000\,007$.
Problem 623: Lambda Count
Mathematical Analysis
Unsigned Stirling Numbers of the First Kind
The count of permutations of with exactly cycles is the unsigned Stirling number of the first kind . Our target is:
Closed-Form Formula
Theorem. For :
where is the -th harmonic number.
Constructive Proof of (2)
Fix element in a cycle of length (). Choose companions from : ways. Arrange the elements in a directed cycle: ways. The remaining elements form the second cycle: ways. Summing:
Recurrence Relation
The Stirling numbers satisfy:
Interpretation: element either inserts into one of positions in an existing cycle (first term, preserving cycles), or forms a new fixed-point cycle (second term, requiring cycles among elements).
For :
Exponential Generating Function
The EGF for permutations with exactly cycles is:
For : , which follows from the exponential formula (the EGF for a single cycle is , and “exactly cycles” is the -th convolution divided by ).
Concrete Values
| 2 | 1 | 1 | 1 |
| 3 | 3/2 | 2 | 3 |
| 4 | 11/6 | 6 | 11 |
| 5 | 25/12 | 24 | 50 |
| 6 | 137/60 | 120 | 274 |
| 7 | 49/20 | 720 | 1764 |
| 8 | 363/140 | 5040 | 13068 |
Verification: corresponds to the permutations , , .
Derivation
Algorithm 1: Direct Formula (primary)
Compute via :
- Compute iteratively.
- Compute using the modular inverse recurrence .
Algorithm 2: Recurrence (alternative)
Use with base case .
Verification
Both methods agree for all up to . Cross-checked against exact rational arithmetic for .
Proof of Correctness
Theorem. for all .
Proof by induction. Base: . Step: .
Lemma (Integrality). is always a positive integer.
Proof. By the recurrence: sum of products of integers. Alternatively, it counts permutations, hence is a non-negative integer, and is positive for .
Proposition (Asymptotic). as , since and .
Complexity Analysis
- Inverse recurrence method: time, space.
- Fermat inverse method: time, space.
- Recurrence method: time, space.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
/*
* Problem 623: Lambda Count
*
* Count permutations of {1,...,n} with exactly 2 cycles.
* This is the unsigned Stirling number [n,2] = (n-1)! * H_{n-1}.
*
* Three methods:
* 1. Direct formula: (n-1)! * sum(k^{-1}, k=1..n-1) mod p
* 2. Recurrence: [n,2] = (n-1)*[n-1,2] + (n-2)!
* 3. Inverse recurrence: inv[k] = -(p/k) * inv[p%k] mod p
*/
const ll MOD = 1e9 + 7;
ll power(ll base, ll exp, ll mod) {
ll result = 1;
base %= mod;
while (exp > 0) {
if (exp & 1) result = result * base % mod;
base = base * base % mod;
exp >>= 1;
}
return result;
}
// Method 1: Direct formula with Fermat inverses
ll solve_direct(int n) {
if (n < 2) return 0;
ll fact = 1, h = 0;
for (int k = 1; k < n; k++) {
fact = fact * k % MOD;
h = (h + power(k, MOD - 2, MOD)) % MOD;
}
return fact * h % MOD;
}
// Method 2: Recurrence [n,2] = (n-1)*[n-1,2] + (n-2)!
ll solve_recurrence(int n) {
if (n < 2) return 0;
ll stir = 1; // [2,2] = 1
ll fact_nm2 = 1; // (n-2)! for n=2 => 0! = 1
for (int m = 3; m <= n; m++) {
fact_nm2 = fact_nm2 * (m - 2) % MOD;
stir = ((ll)(m - 1) * stir % MOD + fact_nm2) % MOD;
}
return stir;
}
// Method 3: Fast inverse recurrence
ll solve_fast(int n) {
if (n < 2) return 0;
vector<ll> inv(n);
inv[1] = 1;
for (int k = 2; k < n; k++) {
inv[k] = -(ll)(MOD / k) % MOD * inv[MOD % k] % MOD;
if (inv[k] < 0) inv[k] += MOD;
}
ll fact = 1, h = 0;
for (int k = 1; k < n; k++) {
fact = fact * k % MOD;
h = (h + inv[k]) % MOD;
}
return fact * h % MOD;
}
int main() {
// Verify small values
int expected[] = {0, 0, 1, 3, 11, 50, 274, 1764, 13068, 109584, 1026576};
for (int n = 0; n <= 10; n++) {
ll v1 = solve_direct(n);
ll v2 = solve_recurrence(n);
ll v3 = (n >= 2) ? solve_fast(n) : 0;
assert(v1 == expected[n] % MOD);
assert(v2 == expected[n] % MOD);
assert(v3 == expected[n] % MOD);
}
// Cross-check all three methods for larger n
for (int n = 2; n <= 1000; n++) {
ll v1 = solve_direct(n);
ll v2 = solve_recurrence(n);
ll v3 = solve_fast(n);
assert(v1 == v2 && v2 == v3);
}
int n = 1000000;
ll ans = solve_fast(n);
cout << "[" << n << ", 2] mod " << MOD << " = " << ans << endl;
return 0;
}
"""
Problem 623: Lambda Count
Count permutations of {1,...,n} with exactly 2 disjoint cycles.
This equals the unsigned Stirling number [n,2] = (n-1)! * H_{n-1}.
Key identity: [n,2] = (n-1)! * sum_{k=1}^{n-1} 1/k
Method 1: Direct formula (n-1)! * H_{n-1} with modular inverses
Method 2: Recurrence [n,2] = (n-1)*[n-1,2] + (n-2)!
Method 3: Exact computation for verification
"""
from math import factorial
from fractions import Fraction
MOD = 10**9 + 7
# --- Method 1: Direct formula with modular arithmetic ---
def lambda_mod_direct(n: int, mod: int):
"""Compute [n,2] = (n-1)! * H_{n-1} mod p using Fermat inverses."""
if n < 2:
return 0
fact = 1
harmonic = 0
for k in range(1, n):
fact = fact * k % mod
harmonic = (harmonic + pow(k, mod - 2, mod)) % mod
return fact * harmonic % mod
# --- Method 1b: Using fast inverse recurrence ---
def lambda_mod_fast(n: int, mod: int):
"""Compute [n,2] = (n-1)! * H_{n-1} mod p using inverse recurrence.
inv[k] = -(p mod k)^{-1} * floor(p/k) mod p
"""
if n < 2:
return 0
inv = [0] * n
inv[1] = 1
for k in range(2, n):
inv[k] = -(mod // k) * inv[mod % k] % mod
fact = 1
harmonic = 0
for k in range(1, n):
fact = fact * k % mod
harmonic = (harmonic + inv[k]) % mod
return fact * harmonic % mod
# --- Method 2: Recurrence ---
def lambda_mod_recurrence(n: int, mod: int):
"""Compute [n,2] via recurrence: [n,2] = (n-1)*[n-1,2] + (n-2)!"""
if n < 2:
return 0
stir = 0 # [2,2] = 1 is handled at n=2
fact_nm2 = 1 # (n-2)! starting at n=2: 0! = 1
stir = 1 # [2,2]
for m in range(3, n + 1):
fact_nm2 = fact_nm2 * (m - 2) % mod # (m-2)!
stir = ((m - 1) * stir + fact_nm2) % mod
return stir if n >= 2 else 0
# --- Method 3: Exact computation ---
def lambda_exact(n: int):
"""Compute exact [n,2] using Fraction arithmetic."""
if n < 2:
return 0
h = Fraction(0)
for k in range(1, n):
h += Fraction(1, k)
return int(factorial(n - 1) * h)
# Compute and verify
# Exact values for small n
expected = {2: 1, 3: 3, 4: 11, 5: 50, 6: 274, 7: 1764, 8: 13068, 9: 109584, 10: 1026576}
for n, val in expected.items():
exact = lambda_exact(n)
assert exact == val, f"Exact: [n={n},2] = {exact}, expected {val}"
mod_dir = lambda_mod_direct(n, MOD)
mod_fast = lambda_mod_fast(n, MOD)
mod_rec = lambda_mod_recurrence(n, MOD)
assert mod_dir == val % MOD
assert mod_fast == val % MOD
assert mod_rec == val % MOD
# Verify three methods agree for larger n
for n in range(2, 500):
v1 = lambda_mod_direct(n, MOD)
v2 = lambda_mod_fast(n, MOD)
v3 = lambda_mod_recurrence(n, MOD)
assert v1 == v2 == v3, f"Mismatch at n={n}: {v1}, {v2}, {v3}"
# Verify combinatorial interpretation: [3,2] = 3
# The 3 permutations with 2 cycles: (1)(23), (2)(13), (3)(12)
from itertools import permutations
def count_cycles(perm):
n = len(perm)
visited = [False] * n
cycles = 0
for i in range(n):
if not visited[i]:
cycles += 1
j = i
while not visited[j]:
visited[j] = True
j = perm[j]
return cycles
for n in range(2, 8):
count = sum(1 for p in permutations(range(n)) if count_cycles(p) == 2)
assert count == lambda_exact(n), f"n={n}: counted {count}, formula gives {lambda_exact(n)}"
print("All verifications passed.")
# Print table
print(f"\n{'n':>4} {'[n,2]':>12} {'(n-1)!':>10} {'H_{n-1}':>12}")
for n in range(2, 11):
val = lambda_exact(n)
fact = factorial(n - 1)
h = Fraction(0)
for k in range(1, n):
h += Fraction(1, k)
print(f"{n:>4} {val:>12} {fact:>10} {str(h):>12}")
# Specific answer for n = 10^6 mod 10^9 + 7
n_large = 10**6
ans = lambda_mod_fast(n_large, MOD)
print(f"\n[{n_large}, 2] mod {MOD} = {ans}")