跳到主要内容

Eulerian Number

注意

下文中的欧拉数特指 Eulerian number。注意与 Euler number,以及 Euler's number(指与欧拉相关的数学常数例如 γ\gammae\mathrm{e})作区分。

在计算组合中,欧拉数(Eulerian Number)是从 11nn 中正好满足 mm 个元素大于前一个元素(具有 mm 个「上升」的排列)条件的排列 个数。定义为:

A(n,m)=nm1A(n, m) = \left\langle \begin{matrix} n\\ m - 1 \end{matrix} \right\rangle

例如,从数字 1133 一共有 44 种排列使得恰好有一个元素比前一个元素大:

排列满足条件的相邻元素个数
1 2 31, 2 & 2, 32
1 3 21, 31
2 1 31, 31
2 3 12, 31
3 1 21, 21
3 2 10

所以按照 A(n,m)A(n, m) 定义:如果 nn 等于 33mm 等于 11,欧拉数值为 44,表示共有 44 个有 11 个元素大于前一个元素的排列。

对于 nnmm 值比较小的欧拉数来说,我们可以直接得到结果:

A(n,m)A(n, m)满足要求的排列个数
A(1,0)A(1, 0)(1)(1)1
A(2,0)A(2, 0)(2,1)(2, 1)1
A(2,1)A(2, 1)(1,2)(1, 2)1
A(3,0)A(3, 0)(3,2,1)(3, 2, 1)1
A(3,1)A(3, 1)(1,3,2),(2,1,3),(2,3,1),(3,1,2)(1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2)4
A(3,2)A(3, 2)(1,2,3)(1, 2, 3)1

公式

可以通过递推或者递归的方法计算欧拉数。

首先,当 mnm \ge nn=0n = 0 时,没有满足条件的排列,即此时欧拉数为 00

其次,当 m=0m = 0 时,只有降序的排列满足条件,即此时欧拉数为 11

最后,考虑在 n1n-1 的排列的基础上插入 nn 从而得到 nn 的排列,由于插入 nn 至多使欧拉数增加 11,所以 A(n,m)A(n, m) 可以仅从 A(n1,m1)A(n-1, m-1) 处和 A(n1,m)A(n-1, m) 处转移得到。

考虑 nn 插入的位置:当 pi1<pip_{i-1} < p_{i} 时,若将 nn 插到 pip_{i} 之前,即将 nn 插入到「上升」中,排列的欧拉数不变;此外,将 nn 插在排列之前,排列的欧拉数也不变;否则,若将 nn 插到其余位置,排列的欧拉数增加 11

考虑从 A(n1,m1)A(n-1, m-1) 转移到 A(n,m)A(n, m),此时需要使欧拉数增加 11,此时不能将 nn 插在「上升」中或者排列开头,共有 n(m1)1=nmn - (m-1) - 1 = n-m 种方案。

考虑从 A(n1,m)A(n-1, m) 转移到 A(n,m)A(n, m),此时需要欧拉数保持不变,只能将 nn 插在「上升」中或者排列开头,共 m+1m+1 种方案。

综上所述,有

A(n,m)={0,m>n or n=0,1,m=0,(nm)A(n1,m1)+(m+1)A(n1,m),otherwise.A(n, m) = \begin{cases} 0, & m > n \text{ or } n = 0, \\ 1, & m = 0, \\ (n-m) \cdot A(n-1, m-1) + (m+1) \cdot A(n-1, m), & \text{otherwise}. \end{cases}

实现

int eulerianNumber(int n, int m) {
if (m >= n || n == 0) return 0;
if (m == 0) return 1;
return (((n - m) * eulerianNumber(n - 1, m - 1)) +
((m + 1) * eulerianNumber(n - 1, m)));
}

习题

中等 (500)