专栏文章

题解:P12369 [蓝桥杯 2022 省 Python B] 全排列的价值

P12369题解参与者 4已保存评论 3

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
3 条
当前快照
1 份
快照标识符
@mipda6yd
此快照首次捕获于
2025/12/03 10:07
3 个月前
此快照最后确认于
2025/12/03 10:07
3 个月前
查看原文
思考价值的本质是什么,发现其实就是把逆序对数换了个说法嘛。所以题目其实是让我们求长度为 nn 的所有排列的逆序对数总和。
直接求肯定是不行的,考虑如何快速计算答案。发现答案可以分拆为两个子问题答案的乘积:求解单个数对贡献以及数对的数量。
考虑单独计算数对 (i,j)(i,j) 产生的贡献。由于 iijj 的相对位置可以自由变换,所以 (i,j)(i,j)12\dfrac{1}{2} 的概率是逆序对。全排列总数为 n!n!,那么 (i,j)(i,j) 的贡献即为 n!2\dfrac{n!}{2} 啦。
接下来考虑这样的数对一共有多少个。这其实等价于求在 nn 个互不相同的小球中选 22 个小球的方案数,即 (n2)=n!2!(n2)!=n(n1)2\displaystyle \binom{n}{2}=\dfrac{n!}{2!(n-2)!}=\dfrac{n(n-1)}{2}
于是答案为:ans=n!2×n(n1)2=n!n(n1)4ans=\dfrac{n!}{2}\times \dfrac{n(n-1)}{2}=\dfrac{n!n(n-1)}{4}
阶乘部分预处理即可,除法用费马小定理算逆元。注意取模要勤快。
附 AC 代码:
CPP
#include<bits/stdc++.h>
#define int long long
#define _ 0
using namespace std;
const int N = 1e6 + 10, mod = 998244353;
int n;
int fac[N];//阶乘 
int qp(int a, int b, int p)//快速幂 
{
	int res = 1;
	while(b)
	{
		if(b & 1) res = res * a % p;
		a = a * a % p;
		b >>= 1;
	}
	return res;
}
void initfac()//预处理阶乘 
{
	fac[0] = 1;
	for(int i = 1; i < N; i ++)
		fac[i] = fac[i - 1] * i % mod;
}
signed main()
{
	initfac();
	cin >> n;
	cout << fac[n] * n % mod * (n - 1) % mod * qp(4ll, mod - 2, mod) % mod;
	return (0^_^0);
}

评论

3 条评论,欢迎与作者交流。

正在加载评论...