这是一个计数问题,而不是构造问题,因此我们可以使用递归来解决它。由于这个问题有两个自然部分,从左看和从右看,把它分解,先解决一个部分。
令b(N, L, R) 为解决方案的数量,让f(N, L) 为N 块的排列数量,以便L 从左侧可见。首先考虑f,因为它更容易。
方法 1
让我们得到初始条件,然后进行递归。如果要全部可见,那么它们必须越来越多地排序,所以
f(N, N) = 1
如果假设可见块比可用块多,那么我们无能为力,所以
f(N, M) = 0 if N < M
如果只有一个块是可见的,那么把最大的放在前面,然后其他的可以按任何顺序跟随,所以
f(N,1) = (N-1)!
最后,对于递归,考虑最高块的位置,比如N 位于左侧的第k 个位置。然后以(N-1 choose k-1) 的方式选择在它前面的块,排列这些块,使L-1 从左侧完全可见,然后将N-k 块按你喜欢的顺序排列在N 后面,给出:
f(N, L) = sum_{1<=k<=N} (N-1 choose k-1) * f(k-1, L-1) * (N-k)!
其实,既然f(x-1,L-1) = 0换成x<L,那我们还不如在L开始k而不是1:
f(N, L) = sum_{L<=k<=N} (N-1 choose k-1) * f(k-1, L-1) * (N-k)!
好的,既然理解了更容易的位,让我们使用f 来解决更难的位b。同样,使用基于最高块位置的递归,再次说N 位于左侧的k 位置。和以前一样,以N-1 choose k-1 的方式选择它之前的块,但现在分别考虑该块的每一侧。对于N 左侧的k-1 块,确保它们中的L-1 完全可见。对于N 右侧的N-k 块,确保R-1 可见,然后颠倒从f 获得的顺序。因此答案是:
b(N,L,R) = sum_{1<=k<=N} (N-1 choose k-1) * f(k-1, L-1) * f(N-k, R-1)
f 在上面已经完全解决了。同样,许多项将为零,所以我们只想取k 这样k-1 >= L-1 和N-k >= R-1 得到
b(N,L,R) = sum_{L <= k <= N-R+1} (N-1 choose k-1) * f(k-1, L-1) * f(N-k, R-1)
方法 2
我再次考虑了这个问题,发现了一种更好的方法来避免求和。
如果您以相反的方式解决问题,即考虑添加最小块而不是最大块,那么f 的递归变得更加简单。在这种情况下,在初始条件相同的情况下,递归是
f(N,L) = f(N-1,L-1) + (N-1) * f(N-1,L)
第一项 f(N-1,L-1) 来自于将最小块放置在最左边的位置,从而增加了一个可见块(因此 L 减少到 L-1),第二项 (N-1) * f(N-1,L),考虑将最小的块放在任何N-1 非前面位置,在这种情况下它是不可见的(因此L 保持固定)。
这种递归的优点是总是减少N,尽管它使查看某些公式变得更加困难,例如f(N,N-1) = (N choose 2)。这个公式很容易从前面的公式中显示出来,尽管我不确定如何从这个更简单的递归中很好地推导出它。
现在,要回到原来的问题并解决b,我们还可以采用不同的方法。与之前的求和不同,将可见块视为以包的形式出现,因此,如果一个块从左侧可见,那么它的包由它右侧和从左侧可见的下一个块前面的所有块组成,并且类似地,如果一个块从右侧可见,那么它的数据包包含它左侧的所有块,直到从右侧可见的下一个块。对除最高块之外的所有对象执行此操作。这使得L+R 数据包。给定数据包,您可以通过反转块的顺序将一个从左侧移动到右侧。因此,一般情况b(N,L,R) 实际上简化为解决b(N,L,1) = f(N,L) 的情况,然后选择将哪些数据包放在左边,哪些放在右边。所以我们有
b(N,L,R) = (L+R choose L) * f(N,L+R)
同样,这种重新表述比以前的版本有一些优势。将后两个公式放在一起,更容易看出整个问题的复杂性。然而,我仍然更喜欢第一种构建解决方案的方法,尽管也许其他人会不同意。总而言之,这表明解决问题的好方法不止一种。
斯特林数字是怎么回事?
正如 Jason 所指出的,f(N,L) 数字正是(无符号)Stirling numbers of the first kind。可以从每个递归公式中立即看到这一点。但是,能够直接看到它总是很高兴,所以就这样吧。
第一类(无符号)斯特林数,表示为S(N,L),计算N 到L 循环的排列数。给定一个用循环表示法编写的排列,我们以规范形式编写排列,方法是从该循环中具有最大数字的循环开始,然后按循环的第一个数字对循环进行递增排序。例如,排列
(2 6) (5 1 4) (3 7)
将被写成规范形式
(5 1 4) (6 2) (7 3)
现在去掉括号,注意如果这些是块的高度,那么从左边算起可见块的数量就是周期数!这是因为每个循环的第一个数字阻塞了循环中的所有其他数字,并且每个连续循环的第一个数字在前一个循环后面是可见的。因此,这个问题实际上只是一种偷偷摸摸的方式,要求您找到斯特林数的公式。