专栏文章
题解:P12369 [蓝桥杯 2022 省 Python B] 全排列的价值
P12369题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mipfmm3z
- 此快照首次捕获于
- 2025/12/03 11:13 3 个月前
- 此快照最后确认于
- 2025/12/03 11:13 3 个月前
P12369 [蓝桥杯 2022 省 Python B] 全排列的价值 题解
思路
分享一种不用逆元的做法。
考虑线性递推。设答案为 ,那么对于前面已知的 ,设它的一种全排列方式为 。

如图,将 的增加视为向这个排列内插入一个 ,算上该序列的头尾,共有 个位置可以插,插在第 个位置上的贡献即为该位置前方元素的数量,即 (因为这时 一定是最大的,前面的所有元素都比它小,后面的所有元素都没它大,所以只对前面有影响)。因此该排列下插入带来的贡献为:
每次不同的插入方法都视为一种答案, 种方法,就需要将原答案数乘 。在 下的 个排列都得计算一遍,合起来就是总答案的 倍与插入带来的总贡献 之和。初始的状态为 ,答案显然为 。于是我们即可得到递推式:
1 & n=2\\
nf(n-1)+\dfrac{n(n-1)}{2}(n-1)! & n>2
\end{cases}$$
时间复杂度 $O(n)$。阶乘采用预处理。
### C++
```cpp
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=1e6+5,mod=998244353;
ll n,ans[N],jc[N]={1,1};
int main()
{
cin>>n;
ans[2]=1;
for(int i=1; i<=N; i++)
jc[i]=jc[i-1]*i%mod;//阶乘预处理
for(int i=3; i<=n; i++)
ans[i]=(i*1ll*ans[i-1]%mod+i*1ll*(i-1)/2ll%mod*1ll*jc[i-1]%mod)%mod;
//记住在常数后面加 ll 防止转 int 炸掉
//由于 i*(i-1) 一定为偶数,所以可以直接 /2 而不用考虑逆元
cout<<ans[n]%mod;
return 0;
}
```
### Python
```python
mod = 998244353
N = 1000005
n = int(input())
ans = [0] * N
ans[2] = 1
jc = [1] * N
for i in range(1, N):
jc[i] = (jc[i-1] * i) % mod
for i in range(3, n + 1):
t1 = (i * ans[i-1]) % mod
t2 = ((i * (i - 1) // 2) % mod) * jc[i-1] % mod
ans[i] = (t1 + t2) % mod
print(ans[n] % mod)
```
upd on 2025/5/5 18:30:添加了 Python 代码。
upd on 2025/6/7 22:05:修改了凌乱冗余的语言描述,增强可读性。相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...