全排列的逆序数和

1 → n 1\rightarrow n 1n的所有排列的逆序数的和

解:
f ( i , j ) f(i,j) f(i,j) 1 → i 1\rightarrow i 1i逆序数为 j j j的排列的方案数, s u m ( i ) sum(i) sum(i) 1 1 1~ i i i的所有排列的逆序数的和。则有公式

  • s u m ( i ) = ∑ j = 0 ( i 2 ) f ( i , j ) ∗ j ( 1 ) sum(i)=\sum_{j=0}^{{i\choose 2}}f(i,j)*j\quad (1) sum(i)=j=0(2i)f(i,j)j(1)
  • i ! = ∑ j = 0 ( i 2 ) f ( i , j ) ( 2 ) i!=\sum_{j=0}^{{i\choose 2}}f(i,j)\quad (2) i!=j=0(2i)f(i,j)(2)

考虑 i i i i + 1 i+1 i+1 d p dp dp过程,初始

  • ∀ k ∈ [ 0 , ( i + 1 2 ) ] \forall k\in[0,{i+1\choose 2}] k[0,(2i+1)] f ( i + 1 , k ) = 0 f(i+1,k)=0 f(i+1,k)=0
  • s u m ( i + 1 ) = ∑ k = 0 ( i + 1 2 ) f ( i + 1 , k ) ∗ k = 0 ( 3 ) sum(i+1)=\sum_{k=0}^{{i+1\choose 2}}f(i+1,k)*k=0\quad (3) sum(i+1)=k=0(2i+1)f(i+1,k)k=0(3)

对于一个 1 → i 1\rightarrow i 1i的逆序数为 j j j的排列,当把 i + 1 i+1 i+1考虑进去时,设逆序数的增量 Δ \Delta Δ,有
0 ≤ Δ ≤ i 0\le\Delta\le i 0Δi

  • 比如 3 , 1 , 2 3,1,2 3,1,2,把 4 4 4放进去
  1. 4 , 3 , 1 , 2 \quad4,3,1,2 4,3,1,2 Δ = 3 \Delta=3 Δ=3
  2. 3 , 4 , 1 , 2 \quad3,4,1,2 3,4,1,2 Δ = 2 \Delta=2 Δ=2
  3. 3 , 1 , 4 , 2 \quad3,1,4,2 3,1,4,2 Δ = 1 \Delta=1 Δ=1
  4. 3 , 1 , 2 , 4 \quad3,1,2,4 3,1,2,4 Δ = 0 \Delta=0 Δ=0

也就意味着,一个 1 → i 1\rightarrow i 1i的逆序数为 j j j的排列能够变成 1 → i + 1 1\rightarrow i+1 1i+1的逆序数为 k ( j ≤ k ≤ j + i ) k(j\le k\le j+i) k(jkj+i)的排列。即 f ( i , j ) f(i,j) f(i,j)会贡献给 f ( i + 1 , k ) ( j ≤ k ≤ j + i ) f(i+1,k)(j\le k\le j+i) f(i+1,k)(jkj+i),让 f ( i + 1 , k ) ( j ≤ k ≤ j + i ) f(i+1,k)(j\le k\le j+i) f(i+1,k)(jkj+i)增加 f ( i , j ) f(i,j) f(i,j)。那么根据式子 ( 3 ) (3) (3) s u m ( i + 1 ) sum(i+1) sum(i+1)增加 f ( i , j ) ∗ k ( j ≤ k ≤ j + i ) f(i,j)*k(j\le k\le j+i) f(i,j)k(jkj+i),再考虑 1 → i 1\rightarrow i 1i的所有逆序数 j j j
s u m ( i + 1 ) = ∑ j = 0 ( i 2 ) ∑ k = j j + i f ( i , j ) ∗ k = ∑ j = 0 ( i 2 ) f ( i , j ) ∗ ( 2 j + i ) ( i + 1 ) 2 = i + 1 2 ( 2 ∑ j = 0 ( i 2 ) f ( i , j ) ∗ j + ∑ j = 0 ( i 2 ) f ( i , j ) ∗ i ) = ( i + 1 ) ∑ j = 0 ( i 2 ) f ( i , j ) ∗ j + ( i + 1 ) ∗ i 2 ∑ j = 0 ( i 2 ) f ( i , j ) 根 据 ( 1 ) ( 2 ) = ( i + 1 ) s u m ( i ) + i ∗ i ! ∗ ( i + 1 ) 2 = ( i + 1 ) s u m ( i ) + i ∗ ( i + 1 ) ! 2 \begin{aligned} sum(i+1)&=\sum_{j=0}^{{i\choose 2}}\sum_{k=j}^{j+i}f(i,j)*k\\ &=\sum_{j=0}^{{i\choose 2}}f(i,j)*\frac{(2j+i)(i+1)}{2}\\ &=\frac{i+1}{2}(2\sum_{j=0}^{{i\choose 2}}f(i,j)*j+\sum_{j=0}^{{i\choose 2}}f(i,j)*i)\\ &=(i+1)\sum_{j=0}^{{i\choose 2}}f(i,j)*j+\frac{(i+1)*i}{2}\sum_{j=0}^{i\choose 2}f(i,j)\quad 根据(1)(2)\\ &=(i+1)sum(i)+\frac{i*i!*(i+1)}{2}\\ &=(i+1)sum(i)+\frac{i*(i+1)!}{2}\\ \end{aligned} sum(i+1)=j=0(2i)k=jj+if(i,j)k=j=0(2i)f(i,j)2(2j+i)(i+1)=2i+1(2j=0(2i)f(i,j)j+j=0(2i)f(i,j)i)=(i+1)j=0(2i)f(i,j)j+2(i+1)ij=0(2i)f(i,j)(1)(2)=(i+1)sum(i)+2ii!(i+1)=(i+1)sum(i)+2i(i+1)!
得到递推式
s u m ( i + 1 ) = ( i + 1 ) s u m ( i ) + i ∗ ( i + 1 ) ! 2 i ≥ 1 sum(i+1)=(i+1)sum(i)+\frac{i*(i+1)!}{2}\quad i\ge 1 sum(i+1)=(i+1)sum(i)+2i(i+1)!i1
迭代一次
s u m ( i + 1 ) = ( i + 1 ) ( i ∗ s u m ( i − 1 ) + ( i − 1 ) ∗ i ! 2 ) + i ∗ ( i + 1 ) ! 2 s u m ( i + 1 ) = ( i + 1 ) ∗ i ∗ s u m ( i − 1 ) + ( i − 1 ) ∗ ( i + 1 ) ! 2 + i ∗ ( i + 1 ) ! 2 \begin{aligned} sum(i+1)&=(i+1)(i*sum(i-1)+\frac{(i-1)*i!}{2})+\frac{i*(i+1)!}{2}\\ sum(i+1)&=(i+1)*i*sum(i-1)+\frac{(i-1)*(i+1)!}{2}+\frac{i*(i+1)!}{2}\\ \end{aligned} sum(i+1)sum(i+1)=(i+1)(isum(i1)+2(i1)i!)+2i(i+1)!=(i+1)isum(i1)+2(i1)(i+1)!+2i(i+1)!
多迭代几次会发现
s u m ( i + 1 ) = s u m ( 1 ) ∗ ∏ j = 2 i + 1 j + ( i + 1 ) ! 2 ∑ j = 1 i j s u m ( 1 ) = 0 = i ∗ ( i + 1 ) ∗ ( i + 1 ) ! 4 s u m ( n ) = n ( n − 1 ) n ! 4 \begin{aligned} sum(i+1)&=sum(1)*\prod_{j=2}^{i+1}j+\frac{(i+1)!}{2}\sum_{j=1}^{i}j\quad sum(1)=0\\ &=\frac{i*(i+1)*(i+1)!}{4}\\ sum(n)&=\frac{n(n-1)n!}{4}\\ \end{aligned} sum(i+1)sum(n)=sum(1)j=2i+1j+2(i+1)!j=1ijsum(1)=0=4i(i+1)(i+1)!=4n(n1)n!

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,这个问题可以使用回溯算法来解决。具体步骤如下: 1. 定义一个局变量ans,用来存储所有满足条件的排列。 2. 定义一个数组used,用来记录每个数字是否被使用过。 3. 定义一个递归函数backtrack,用来生成排列。 4. 在backtrack函数中,首先判断当前排列是否已经有n个数字了,如果是,则将其加入ans中。 5. 如果排列长度还没有达到n,那么就遍历所有可能的数字,如果这个数字没有被使用过,并且不在约束条件中,那么就将这个数字加入排列中,并将used数组中对应的位置标记为已使用。 6. 递归调用backtrack函数,继续生成下一个数字。 7. 当backtrack函数返回时,需要将排列中最后一个数字弹出,并将used数组中对应的位置标记为未使用,以便后续的排列生成。 最后,将ans中的所有排列按照字典序的序输出即可。下面是代码实现: ```python n = 5 # 排列长度 Q = 2 # 约束数量 x = [2, 4] # 约束条件 ans = [] # 存储所有满足条件的排列 used = [False] * (n+1) # 记录每个数字是否被使用过 def backtrack(path): if len(path) == n: ans.append(path[:]) return for i in range(1, n+1): if not used[i] and i not in x: used[i] = True path.append(i) backtrack(path) path.pop() used[i] = False backtrack([]) ans.sort(reverse=True) for a in ans: print(" ".join(str(x) for x in a)) ``` 运行结果为: ``` 5 3 1 4 2 5 3 1 2 4 5 1 3 4 2 5 1 3 2 4 3 5 1 4 2 3 5 1 2 4 3 1 5 4 2 3 1 5 2 4 1 5 3 4 2 1 5 3 2 4 1 3 5 4 2 1 3 5 2 4 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值