题意:把所有 n n n 元排列按字典序从小到大排成一列,求其中有多少长度为 m m m 的连续子串为 1 , 2 ⋯ , m 1, 2\cdots, m 1,2⋯,m 的 m m m 元排列,方案数模 1 e 9 + 7 1\rm e9+7 1e9+7。 t t t 组询问, m < n m
解法:首先所有 m m m 元排列只有可能出现在两个排列中间或者独属于某一个 n n n 元排列。首先,独属于某一个 n n n 元排列方案数非常简单——在一个 n n n 元排列中选取一个长度为 m m m 的连续子串,位置共有 n − m + 1 n-m+1 n−m+1 个,剩下数字直接排列即可,方案数为 ( n − m + 1 ) m ! ( n − m ) ! = m ! ( n − m + 1 ) ! \displaystyle (n-m+1)m!(n-m)!=m!(n-m+1)! (n−m+1)m!(n−m)!=m!(n−m+1)!。
下面考虑跨越两个 n n n 元排列的 m m m 元排列方案数。注意到排列的一个重要性质:假定当前排列为 p 1 , p 2 , ⋯ , p n p_1,p_2,\cdots, p_n p1,p2,⋯,pn,且满足 ∃ k ∈ [ 1 , n − 1 ] \exist k\in[1,n-1] ∃k∈[1,n−1], ∀ i ∈ [ k + 1 , n − 1 ] , p i > p i + 1 \forall i\in [k+1,n-1],p_i>p_{i+1} ∀i∈[k+1,n−1],pi>pi+1,且 p k < p k + 1 p_k
记这样的下标 k k k 为折返点,考虑 k k k 可能的位置。又记当前的 m m m 元排列可以被分为前后两个 n n n 元排列的前后缀,其中后面一个排列的前缀长度为 i i i,则前半部分长度为 m − i m-i m−i。同时考虑将当前的 m m m 元排列向前扩展到一个大小为 n n n 的范围。
大致可以分为这样的位置状态,下面会解释为什么一定是这样的。将 i i i 与 k k k 的关系粗略分为以下两种——
折返点位于扩展点之后,大致位置如下所示:
或者如下这样:
只要折返点不在橙色区段,那么根据排列的性质,折返点前都不会受到影响,因而红色段和橙色段是完全一样的。那么为了让绿色段和红色段构成一个 m m m 元排列,大于 m m m 的剩下数字就只能放在蓝色段。因而,枚举前缀 i i i 的长度,则红色段方案数为 ( m i ) i ! \displaystyle {m\choose i}i! (im)i!,蓝色段方案数为 ( n − m ) ! (n-m)! (n−m)!,绿色段由于数字在红色段选定,因而只有排列的方案也就是 ( m − i + 1 ) ! (m-i+1)! (m−i+1)!。但是由于需要存在折返点,因而蓝色段和绿色段的总序列不可以是完全单调递减的,即扣去蓝色段单调递减和绿色段同时单调递减这一种情况,因而可以得到这部分的答案为 ∑ i = 1 m − 1 ( m i ) i ! ( ( n − m ) ! ( m − i + 1 ) ! − 1 ) \displaystyle \sum_{i=1}^{m-1} {m\choose i}i!((n-m)!(m-i+1)!-1) i=1∑m−1(im)i!((n−m)!(m−i+1)!−1)。打开组合数,容易得到方案数为 ( m − 1 ) m ! ( n − m ) ! − m ! ∑ i = 1 m − 1 1 i ! \displaystyle (m-1)m!(n-m)!-m!\sum_{i=1}^{m-1}\frac{1}{i!} (m−1)m!(n−m)!−m!i=1∑m−1i!1。
折返点位于前缀部分(橙色)
这种情况其实是不存在的。显然,紫线前的和红色段中对应紫线位置之前的地方都是不变的。考虑当前要交换到前面来的元素—— p j p_j pj,如果这个 p j p_j pj 位于绿色段,那么这个 p j p_j pj 就会调换到红色区段来,发生重复;那么调换位置必然位于蓝色段。同时,被交换的第一个数——即紫色段右侧的第一个数,势必会被交换到后面的某一个地方。那么,无论如何要么是绿色段的一个值进入了红色段,要么是橙色部分的值没有进入红色段,始终会让红色段的数字集合与橙色段的不同(由于绿色段是共用的,因而橙色段必须和红色段数字集合相同),从而发生冲突。因而这部分答案为 0 0 0。
因而总答案为 m ! ( n − m + 1 ) ! + ( m − 1 ) m ! ( n − m ) ! − m ! ∑ i = 1 m − 1 1 i ! \displaystyle m!(n-m+1)!+(m-1)m!(n-m)!-m!\sum_{i=1}^{m-1}\dfrac{1}{i!} m!(n−m+1)!+(m−1)m!(n−m)!−m!i=1∑m−1i!1,经过预处理可以 O ( 1 ) O(1) O(1) 的计算。