[COGS 2066]七十与十七
http://218.28.19.228/cogs/problem/problem.php?pid=2066
【题目描述】
七十君最近爱上了排序算法,于是Ta让十七君给Ta讲冒泡排序。
十七君给七十君讲完了冒泡排序以后,七十君回家苦思冥想,又创造了一种名
为七十排序的算法。下面是这个算法排序一个排列的过程:
首先从左到右扫描每个相邻数对。如果这两个数是逆序的,则将第二个数(也
就是小的数)放在整个排列的开头,其他数位置不变,并把计数器加一。如果
没有逆序的相邻数对了,就说明已经排好序了,算法终止。
七十君认为计数器的值反映了这个算法的运行时间。但十七君觉得七十君发明
的这个算法会很慢,所以他请你帮忙算算,对于所有长度为n的排列P,
的值,这里f(P)表示排列P运行算法结束时计数器的值。
【输入格式】
一行一个整数n。
【输出格式】
如果E(n)=a/b,求c使得
bc 三 a (mod 10^9+7)
并输出,其中0≤c<10^9+7,如果e不存在输出-1。
【样例输入】
4【样例输出】
250000005【提示】
对于排列4 1 3 2,算法结束时计数器的值为5。
4 1 3 2,4和1形成逆序,将1放到排列最前方。
1 4 3 2,4和3形成逆序,将3放到排列最前方。
3 1 4 2,3和1形成逆序,将1放到排列最前方。
1 3 4 2,4和2形成逆序,将2放到排列最前方。
2 1 3 4,2和1形成逆序,将1放到排列最前方。
1 2 3 4,现在排列已经排序完毕。
E(4)=3.25。
数据范围与约定
对于20%的数据,n≤8。
对于40%的数据,n≤30。
对于60%的数据,n≤200。
对于1OO%的数据,n≤10^5。
设$\sum_{P.len = N} f(P) = F(N)$。观察算法流程可以发现当扫描到第N个元素时,前N-1个元素一定有序,所以我们可以考虑递推求解F函数。现假设P为1到N的排列,最后一个元素为i,而我们已经事先花费$N * F(N-1) + N!$的时间,让所有N排列的前N-1个元素有序并将最后一个元素移至开头。
现在处理一个长度为N的满足$A_1 = N, A_i = i-1(1 < i \leq N)$的排列A,设将它排序所需时间为g(N)。考虑这一过程,我们仍需先将这一排列的前N-1个元素排序,然后将最后一个元素($A_N = N-1$)移至开头,此时新序列的第N个元素已经就位,而前N-1个元素仍满足”排列A“的性质,再按此过程处理一下就可以了。从而有$$g(1) = 0, g(N) = g(N-1) + 1 + g(N-1)(N > 1)$$ 解出$g(N) = 2^{N-1} - 1$。
那么我们就可以得到$$F(N) = N \times (F(N-1) + N!) + (N-1)! \times (\sum_{i = 1}^{N-1} g(i))$$那么$$E(N) = E(N-1) + \frac{2^{N-1} - 1}{N}$$ 把每轮的1/N改成N的乘法逆元即可。
现在处理一个长度为N的满足$A_1 = N, A_i = i-1(1 < i \leq N)$的排列A,设将它排序所需时间为g(N)。考虑这一过程,我们仍需先将这一排列的前N-1个元素排序,然后将最后一个元素($A_N = N-1$)移至开头,此时新序列的第N个元素已经就位,而前N-1个元素仍满足”排列A“的性质,再按此过程处理一下就可以了。从而有$$g(1) = 0, g(N) = g(N-1) + 1 + g(N-1)(N > 1)$$ 解出$g(N) = 2^{N-1} - 1$。
那么我们就可以得到$$F(N) = N \times (F(N-1) + N!) + (N-1)! \times (\sum_{i = 1}^{N-1} g(i))$$那么$$E(N) = E(N-1) + \frac{2^{N-1} - 1}{N}$$ 把每轮的1/N改成N的乘法逆元即可。