再次看了下两年前的题解,觉得还蛮有意思的hhh。不过在一些部分可能表述没那么好。写一份修正版的。
(ps:难顶。修改不可导入外部md,导入就新创建,搞不定了)
题意:给定 n ! n! n!个 n n n的排列,按字典序从小到大连成一个序列,例如3的情况为:[1,2,3, 1,3,2, 2,1,3 ,2,3,1 ,3,1,2 ,3,2,1]。问其中子段长度为n,且和 s u m = n × ( n − 1 ) ÷ 2 sum=n\times(n-1)\div2 sum=n×(n−1)÷2的序列有多少?
(题意来自于:https://www.cnblogs.com/pkgunboat/archive/2018/12/31/10201676.html @维和战艇机,感谢你这么好的总结方式,借用一下希望不要介意)
思路(非官方题解):官方题解下面有种方法是:There is also a simple recurrence counting the same answer, found by arsijo:d(n)=(d(n−1)+(n−1)!−1)⋅n,我比赛时是用这个方法。
现在讨论可能计入答案的情况,分为以下两种情况。
- n ! n! n!个组成序列的排列。以3为例,[{1,2,3}, {1,3,2}, {2,1,3} ,{2,3,1} ,{3,1,2} ,{3,2,1}],所有大括号内的都计入答案。
- 两个相邻排列组成的答案。也就是一部分在一个排列中,另一部分在下一个排列中的情况,比如[1,{2,3,1},3,2,…],{2,3}属于前一部分,{1}属于后一部分。
显而易见,第一种有 n ! n! n!种情况,接下来推第二种:
首先需要证明,这种情况下的子串,一定都是由n个不同数字组成的情况。有兴趣的同学可以看下,没兴趣的可以跳过证明部分。
设符合的情况所处子段为 p 1 , p 2 p1,p2 p1,p2,其中,在 p 1 p1 p1中长度为 k k k,那么在 p 2 p2 p2中,长度为 n − k n-k n−k,以及剩余长度为 k k k。如图所示。
此处用反证法来证明,假设存在一个上述情况,符合和为 n × ( n − 1 ) ÷ 2 n\times(n-1)\div2 n×(n−1)÷2,且不为n个不同数字组成的情况。
假设上图中,从左往右分别是四块区域,编号为①、②、③、④。其中,①+②= p 1 p1 p1,③+④= p 2 p2 p2。
证明1: ∑ ① + ∑ ③ = n × ( n − 1 ) ÷ 2 \sum①+\sum③=n\times(n-1)\div2 ∑①+∑③=n×(n−1)÷2, ∑ ② + ∑ ④ = n × ( n − 1 ) ÷ 2 \sum②+\sum④=n\times(n-1)\div2 ∑②+∑④=n×(n−1)÷2
此时,通过定理1,可以推出结论1。
结论1:③区域字典序等于①时,也就是③=①,此时②+③=②+①,可计入答案。
由③区域字典序一定大于等于①,我们接下来讨论③字典序大于①的情况。
证明2:如果③字典序大于①,②部分一定是字典序降序。
推导:反证法。如果②部分不是字典序降序,由于题意 p 2 p2 p2是 p 1 p1 p1的next permutation,此时④会是②的next permutation,③部分不会改变,③字典序等于①,与题意不符。
此处需要科普下next permutation的排列变动情况。
定理1:对于 x x x p k p m p m − 1 . . p 1 xxxp_kp_mp_{m-1}..p_1 xxxpkpmpm−1..p1,其中 p m > p m − 1 > . . . > p k > . . . > p 1 p_m>p_{m-1}>...>p_k>...>p_1 pm>pm−1>...>pk>...>p1, x x x xxx xxx表示任意数。该部分的next permutation为 x x x p k + 1 p 1 . . . p k p k + 2 . . . p m xxxp_{k+1}p_1...p_kp_{k+2}...p_m xxxpk+1p1...pkpk+2...pm。
不想证明。
此处添加定义1: p k p_k pk为第一个导致字典序不降序的数字。
证明3:对于定理1中的 p k p m p m − 1 . . p 1 p_kp_mp_{m-1}..p_1 pkpmpm−1..p1和 p k + 1 p 1 . . . p k p k + 2 . . . p m p_{k+1}p_1...p_kp_{k+2}...p_m pk+1p1...pkpk+2...pm,从左往右取相同的长度 l e n ( 1 < l e n < m + 1 ) len(1<len<m+1) len(1<len<m+1)下,前者大于后者。
证明:当 l e n = 2 len=2 len=2时, p m − p 1 > p k + 1 − p k ⇒ p m + p k > p k + 1 + p 1 p_m-p_1>p_{k+1}-p_k\Rightarrow p_m+p_k>p_{k+1}+p_1 pm−p1>pk+1−pk⇒pm+pk>pk+1+p1。
后续证明写起来有点麻烦。不想写,鸽了。
在两者序号没相交时,由于前者每个添加的数字都大于后者 ,以及差距一定是大于 l e n = 2 len=2 len=2情况;
两者序号相交时,把中间相交部分抵消掉,剩下的跟上面情况差不多。证明3证毕。
利用以上证明定理定义,来证明结论2。
结论2:③区域字典序大于①时,不存在②+③可计入答案的情况。
设③的从左往右第m位的数字是 a m a_m am。
由证明2,对 p 1 p_1 p1而言,从右往左可以作为第一个导致字典序不降序的数字是 a n − k a_{n-k} an−k。以下对第一个导致字典序不降序的数字进行讨论。
假设1:作为第一个导致字典序不降序的数字是 a n − k a_{n-k} an−k。
此时next permutation后,由定理1,变为 a n − k ′ a_{n-k}^{'} an−k′。且 a n − k ′ > a n − k a_{n-k}^{'}>a_{n-k} an−k′>an−k。
此时 ③ = ∑ i = 1 n − k − 1 a i + a n − k ′ > ∑ i = 1 n − k a i = ① ③=\sum_{i=1}^{n-k-1}a_i+a_{n-k}^{'}>\sum_{i=1}^{n-k}a_i=① ③=∑i=1n−k−1ai+an−k′>∑i=1n−kai=①。又 ① + ② = n × ( n − 1 ) ÷ 2 ①+②=n\times(n-1)\div2 ①+②=n×(n−1)÷2,则 ③ + ② > n × ( n − 1 ) ÷ 2 ③+②>n\times(n-1)\div2 ③+②>n×(n−1)÷2,不计入答案。
假设2:作为第一个导致字典序不降序的数字是 a 1 a_1 a1。
此时没有next permutation,没有 p 2 p_2 p2,不计入答案。
假设3:作为第一个导致字典序不降序的数字是 a j ( 1 < j < n − k ) a_{j}(1<j<n-k) aj(1<j<n−k)。
由证明③, ③ < ① ③<① ③<①,不计入答案。
至此,结论2证毕。
由结论1和结论2,这种情况下的子串,一定都是由n个不同数字组成的情况证毕。证明部分完结。
答案统计部分开始。
首先固定③部分长度为k,由排列组合,易得②部分组合种数 A n k A_n^k Ank种。
此时对于②部分长度为n-k,为n个数字删去②中k个数字后剩下的数字组合。排列组合共有 ( n − k ) ! (n-k)! (n−k)!种。但由于对于②中字典序最大的,此时的next permutation的前部分已经不会③了,无法计入答案。因此计入答案只有 ( n − k ) ! − 1 (n-k)!-1 (n−k)!−1种。
总结,对于2的情况,计入答案的情况为 A n k × [ ( n − k ) ! − 1 ] A_n^k\times[(n-k)!-1] Ank×[(n−k)!−1]种。
综上所述,答案是 n ! + A n k × [ ( n − k ) ! − 1 ] n!+A_n^k\times[(n-k)!-1] n!+Ank×[(n−k)!−1]。
代码就不再打一遍了。hh
#include<stdio.h>
typedef long long ll;
const int maxn = 1e6 + 5;
const ll Mod = 998244353;
ll a,jie[maxn],djie[maxn],n,res; //jie,djie分别是阶乘和A(n,n-k),res是结果
int main()
{
scanf("%I64d",&n);
jie[0] = 1; djie[0] = 1;
for(a = 1;a <= n;a ++)
{
jie[a] = jie[a-1] * a % Mod;
djie[a] = djie[a-1] * (n+1-a) % Mod;
}
res = jie[n];
for(a = 2;a <= n-1;a ++)
res = (res + (jie[a] - 1) * djie[n-a] % Mod) % Mod;
printf("%I64d\n",res);
return 0;
}
以下是二年前版本
题意:给n!个n的排列,按字典序从小到大连成一条序列,例如3的情况为:[1,2,3, 1,3,2, 2,1,3 ,2,3,1 ,3,1,2 ,3,2,1],问其中长度为n,且和为sum=n*(n+1)/2的序列有多少个?
(题意来自于:https://www.cnblogs.com/pkgunboat/archive/2018/12/31/10201676.html @维和战艇机,感谢你这么好的总结方式,借用一下希望不要介意)
思路(非官方题解):官方题解下面有种方法是:There is also a simple recurrence counting the same answer, found by arsijo:d(n)=(d(n−1)+(n−1)!−1)⋅n,我比赛时是用这个方法。
如官方题解思路,有两种n长度的子序列符合【和为n*(n-1)/2】:
第一种为n!个组成序列的排列;
第二种为一部分在一个排列中,另一部分在下一个排列中的排列。
显而易见,第一种有n!种情况,那下面来推第二种:
对于一个n长度的排列,假设我们先固定前k个元素,那么对于包含这些前k个元素固定的片段,是一系列①前k个元素固定;②后n-k个元素按照字典序从小到大的排列连接而成的,假设这一系列排列的数量为m。
发现这个有什么用呢?现在取出上面那段片段,我们来寻找里面排列为③使用一个排列后n-k个元素④使用下一个排列前k个元素的排列的数量,在上面片段中,能找到的排列都满足,而又由于这些排列夹在上面排列两两之间,可得数量为m-1。(就像对于一个队伍的小朋友,假设两两之间插入一个小朋友,那么插入小朋友的数量为原队伍小朋友的数量-1)。
那么有没有漏网之鱼呢?答案是没有。这个草稿纸上画下,你就明白了。m中满足条件的有m-1种,说明只有一种是不满足的。对于假设考虑只满足③的,那么片段的第一个排列是不满足的,考虑只满足④的话,片段的最后一个排列是不满足的。就不展开了。(不会暴露楼主不想打,,,咔咔)
现在还有一个问题,就是m未知,现在来求m:
由①,则有A(n,n-k)种;
而对于①的每种情况
由②,有k!种,又由解释需要-1,则有(k!-1)种情况。
至此可以得到一个重要的信息,列为③使用一个排列后n-k个元素④使用下一个排列前k个元素的排列的数量 = A(n,n-k)*(k!-1)。
知道上述公式后,来求答案:
k∈[1,n];
当k=n时,其实就是组成序列的排列,所以用组成序列排列的公式:n!;
当k!=n时,用上面得出的公式A(n,n-k)*(k!-1);
因此答案是n!+∑(k from 1 to n-1) [A(n,n-k)×(k!-1)]。
k)*(k!-1)。
知道上述公式后,来求答案:
k∈[1,n];
当k=n时,其实就是组成序列的排列,所以用组成序列排列的公式:n!;
当k!=n时,用上面得出的公式A(n,n-k)*(k!-1);
因此答案是n!+∑(k from 1 to n-1) [A(n,n-k)×(k!-1)]。
代码我就不再贴一遍了。