DTOJ 4147. 「NOI2018」冒泡排序

题意

最近,小 S 对冒泡排序产生了浓厚的兴趣。为了问题简单,小 S 只研究对 1 1 1 n n n 的排列的冒泡排序。

下面是对冒泡排序的算法描述。

输入:一个长度为 n 的排列 p[1...n]
输出:p 排序后的结果。
for i = 1 to n do
	for j = 1 to n - 1 do
		if(p[j] > p[j + 1])
			交换 p[j] 与 p[j + 1] 的值

冒泡排序的交换次数被定义为交换过程的执行次数。可以证明交换次数的一个下界是 1 2 ∑ i = 1 n ∣ i − p i ∣ \frac 1 2 \sum_{i=1}^n \lvert i - p_i \rvert 21i=1nipi,其中 p i p_i pi 是排列 p p p 中第 i i i 个位置的数字。如果你对证明感兴趣,可以看提示。

小 S 开始专注于研究长度为 n n n 的排列中,满足交换次数 = 1 2 ∑ i = 1 n ∣ i − p i ∣ = \frac 1 2 \sum_{i=1}^n \lvert i - p_i \rvert =21i=1nipi 的排列(在后文中,为了方便,我们把所有这样的排列叫「好」的排列)。他进一步想,这样的排列到底多不多?它们分布的密不密集?

小 S 想要对于一个给定的长度为 n n n 的排列 q q q,计算字典序严格大于 q q q 的“好”的排列个数。但是他不会做,于是求助于你,希望你帮他解决这个问题,考虑到答案可能会很大,因此只需输出答案对 998244353 998244353 998244353 取模的结果。

下面是对本题每个测试点的输入规模的说明。

对于所有数据,均满足 T = 5 T = 5 T=5(样例可能不满足)。

n m a x n_\mathrm{max} nmax 表示每组数据中 n n n 的最大值, ∑ n \sum n n 表示所有数据的 n n n 的和。

测试点$n_\mathrm{max} =$ $\sum n \leq$ 特殊性质
1$8$ $5 \ n_\mathrm{max}$
2$9$
3$10$
4$12$
5$13$
6$14$
7$16$
8
9$17$
10$18$
11
12$122$ $700$ $\forall i \enspace q_i = i$
13$144$
14$166$
15$200$
16$233$
17$777$ $4000$ $\forall i \enspace q_i = i$
18$888$
19$933$
20$1000$
21$266666$ $2000000$ $\forall i \enspace q_i = i$
22$333333$
23$444444$
24$555555$
25$600000$
「提示」

下面是对交换次数下界是 1 2 ∑ i = 1 n ∣ i − p i ∣ \frac 1 2 \sum_{i=1}^n \lvert i - p_i \rvert 21i=1nipi 的证明。

排序本质上就是数字的移动,因此排序的交换次数应当可以用数字移动的总距离来描述。对于第 i i i 个位置,假设在初始排列中,这个位置上的数字是 pi,那么我们需要将这个数字移动到第 p i p_i pi 个位置上,移动的距离是 ∣ i − p i ∣ \lvert i - p_i \rvert ipi。从而移动的总距离就是 ∑ i = 1 n ∣ i − p i ∣ \sum_{i=1}^n \lvert i - p_i \rvert i=1nipi,而冒泡排序每次会交换两个相邻的数字,每次交换可以使移动的总距离至多减少 2 2 2。因此 1 2 ∑ i = 1 n ∣ i − p i ∣ \frac 1 2 \sum_{i=1}^n \lvert i - p_i \rvert 21i=1nipi 是冒泡排序的交换次数的下界。

并不是所有的排列都达到了下界,比如在 n = 3 n = 3 n=3 的时候,考虑排列 3   2   1 3 \ 2 \ 1 3 2 1,这个排列进行冒泡排序以后的交换次数是 3 3 3,但是 1 2 ∑ i = 1 n ∣ i − p i ∣ \frac 1 2 \sum_{i=1}^n \lvert i - p_i \rvert 21i=1nipi 只有 2 2 2

题解

首先考虑达到界的要求:即每个元素都不会朝目标位置的反方向移动。如果原序列是递增的那肯定没有问题,所以问题出在逆序对上,又发现单纯的每一对逆序对是不会超过下界的,只有出现长度为 3 3 3的下降子序列时,中间的元素会向两边各一定一次,一定会超出下界。故题目转化为没有大于 2 2 2的下降序列的排列个数。
考虑进一步做更直观的转化:即每增加一个数,如果它小于当前的最大值,那么它只能取剩下的最小值,否则无限制。于是可以列出DP: f [ i ] [ j ] f[i][j] f[i][j]为前 i i i个最大值为j的方案数,把它改好看一点(转移时下标递增)变成: f [ i ] [ j ] f[i][j] f[i][j]为还要放 i i i个,有 j j j个无限制的方案数。转移有 f [ i ] [ j ] = f [ i − 1 ] [ k < = j ] f[i][j]=f[i-1][k<=j] f[i][j]=f[i1][k<=j],前缀和优化一下变成 f [ i ] [ j ] = f [ i − 1 ] [ j ] + f [ i ] [ j − 1 ] f[i][j]=f[i-1][j]+f[i][j-1] f[i][j]=f[i1][j]+f[i][j1]。这显然可以转成路径问题,用组合数可以 O ( 1 ) O(1) O(1)计算。
再考虑字典序限制,对于每个合法的前缀,使下一个元素大于原来的排列,求出无限制的元素个数(树状数组)后,可以直接用 f f f计算。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值