三行代码解决 “全排列的价值”(2022省赛pythonA组)
置顶代码:
from math import factorial n = int(input()) print(factorial(n) *(n-1)*n//4 % 998244353)
一、试题 G: 全排列的价值
【问题描述】
对于一个排列 A = ( a 1 , a 2 , ⋅ ⋅ ⋅ , a n ) A = (a_1, a_2, · · · , a_n) A=(a1,a2,⋅⋅⋅,an),定义价值 c i c_i ci 为 a 1 a_1 a1 至 a i − 1 a_i−1 ai−1 中小于 a i a_i ai 的数的个数,即 c i = ∣ { a j ∣ j < i , a j < a i } ∣ c_i = |\{a_j| j < i, a_j < a_i \}| ci=∣{aj∣j<i,aj<ai}∣。定义 A 的价值为 ∑ i = 1 n c i ∑^n_{i=1} c_i ∑i=1nci。给定 n n n,求 1 至 n n n 的全排列中所有排列的价值之和。
【输入格式】
输入一行包含一个整数 n 。
【输出格式】
输出一行包含一个整数表示答案,由于所有排列的价值之和可能很大,请输出这个数除以 998244353 的余数。
【样例】
-
【样例输入 1】
3
-
【样例输出 1】
9
-
【样例输入 2】
2022
-
【样例输出 2】
593300958
【样例说明】
1 至 3 构成的所有排列的价值如下:
- (1, 2, 3) : 0 + 1 + 2 = 3 ;
- (1, 3, 2) : 0 + 1 + 1 = 2 ;
- (2, 1, 3) : 0 + 0 + 2 = 2 ;
- (2, 3, 1) : 0 + 1 + 0 = 1 ;
- (3, 1, 2) : 0 + 0 + 1 = 1 ;
- (3, 2, 1) : 0 + 0 + 0 = 0 ;
故总和为 3 + 2 + 2 + 1 + 1 = 9。
二、Python 代码
from math import factorial
n = int(input())
print(factorial(n) *(n-1)*n//4 % 998244353)
三、题解
本质上是利用递推公式求每种排列的顺序对(相对逆序对而言)的数量。
1 ~ n构成的全排列,可以通过插入n+1来构成1 ~ n+1 的全排列。而插入一个比原先排列中的数都大的数时,增加顺序对的个数只和插入位置相关。
例如:
1、2构成的全排列可以通过插入3,构成1、2、3构成的全排列。
(1,2): = 1
- (3,1,2)= 1+0 = 1
- (1,3,2)= 1+1 = 2
- (1,2,3)= 1+2 = 3
(2,1):= 0
- (3,2,1)= 0+0 = 0
- (2,3,1)= 0+1 = 1
- (2,1,3)= 0+2 = 2
P
n
P^n
Pn :表示 1 ~ n 全排列的价值
N
(
n
)
N(n)
N(n):表示 1 ~ n 全排列的数量
同理 1 ~ n-1 的全排列中插入 n,每个排列有n个插入位置(0 ~ n-1),每个插入位置带来的价值和下标相同。计算 1 ~ n全排列的价值时,其构成主要是两部分:原有排列的价值:
P
n
−
1
P^{n-1}
Pn−1产生的、新插入n+1后新产生的价值。
P
n
−
1
P^{n-1}
Pn−1被重复计算n遍,原有价值 =
P
n
−
1
×
n
P^{n-1} \times n
Pn−1×n
对于1 ~ n-1 的全排列中每个排列,插入n后会产生
∑
i
=
0
n
−
1
i
\sum_{i=0}^{n-1}i
∑i=0n−1i的价值,新产生的价值 =
N
(
n
−
1
)
×
∑
i
=
0
n
−
1
i
=
(
n
−
1
)
!
×
(
n
(
n
−
1
)
2
)
=
n
!
×
(
n
−
1
)
/
2
N(n-1) \times\sum_{i=0}^{n-1}i = (n-1)!\times(\frac{n(n-1)}{2})=n!\times(n-1)/2
N(n−1)×∑i=0n−1i=(n−1)!×(2n(n−1))=n!×(n−1)/2
递推得到 P n = n ! × ( n − 1 ) n / 4 P^n = n!\times(n-1)n/4 Pn=n!×(n−1)n/4