排 列 最 小 值 排列最小值 排列最小值
正 解 部 分 \color{red}{正解部分} 正解部分
首先排列中第 i i i 个元素作为前 i i i 个元素的最小值的概率为 1 i \frac{1}{i} i1,
设
f
[
i
]
f[i]
f[i] 表示排列第
i
i
i 个元素是否为前
i
i
i 个元素的最小值, 值为
0
/
1
0/1
0/1,
根据题目要求, 期望为
a
n
s
=
(
∑
i
=
1
n
f
[
i
]
)
2
=
∑
i
=
1
n
∑
j
=
1
n
f
[
i
]
f
[
j
]
ans = \left( \sum\limits_{i=1}^n f[i] \right)^2 = \sum\limits_{i=1}^n \sum\limits_{j=1}^n f[i]f[j]
ans=(i=1∑nf[i])2=i=1∑nj=1∑nf[i]f[j],
当
i
=
j
i = j
i=j 时,
f
[
i
]
f
[
j
]
=
1
f[i]f[j] = 1
f[i]f[j]=1 的概率为
1
i
\frac{1}{i}
i1, 在上式对期望的贡献为
∑
i
=
1
n
1
i
\sum\limits_{i=1}^n \frac{1}{i}
i=1∑ni1 .
当
i
!
=
j
i\ != j
i !=j 时,
f
[
i
]
f
[
j
]
=
1
f[i]f[j] = 1
f[i]f[j]=1 的概率为
1
i
×
1
j
\frac{1}{i} \times \frac{1}{j}
i1×j1,
在上式对期望的贡献为
∑
i
=
1
n
1
i
(
(
∑
j
=
1
n
1
j
)
−
1
i
)
=
(
∑
i
=
1
n
1
i
)
2
−
∑
i
=
1
n
1
i
2
\sum\limits_{i=1}^n \frac{1}{i}\left( (\sum\limits_{j=1}^n \frac{1}{j}) - \frac{1}{i}\right) = \left(\sum\limits_{i=1}^n\frac{1}{i}\right)^2 - \sum\limits_{i=1}^n \frac{1}{i^2}
i=1∑ni1((j=1∑nj1)−i1)=(i=1∑ni1)2−i=1∑ni21 .
所以 a n s ans ans 的期望为 ∑ i = 1 n 1 i + ( ∑ i = 1 n 1 i ) 2 − ∑ i = 1 n 1 i 2 \sum\limits_{i=1}^n \frac{1}{i}+\left(\sum\limits_{i=1}^n\frac{1}{i}\right)^2 - \sum\limits_{i=1}^n \frac{1}{i^2} i=1∑ni1+(i=1∑ni1)2−i=1∑ni21,
然后使用 a n s ans ans 乘上 n ! n! n! 即为题目中的答案 .
实 现 部 分 \color{red}{实现部分} 实现部分
#include<bits/stdc++.h>
#define reg register
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int maxn = 1e5 + 10;
const int mod = 998244353;
int N;
int Q_;
int inv[maxn];
int fac[maxn];
int sum_1[maxn];
int sum_2[maxn];
void Work(){
N = read();
int Ans = (sum_1[N] - sum_2[N] + mod) % mod;
Ans = (1ll*Ans + (1ll*sum_1[N]*sum_1[N]%mod)) % mod;
Ans = 1ll*Ans*fac[N] % mod;
printf("%d\n", Ans);
}
int main(){
Q_ = read();
fac[0] = 1; for(reg int i = 1; i < maxn; i ++) fac[i] = 1ll*fac[i-1]*i % mod;
inv[1] = 1; for(reg int i = 2; i < maxn; i ++) inv[i] = ((-1ll*mod/i*inv[mod%i])%mod + mod) % mod;
for(reg int i = 1; i < maxn; i ++){
sum_1[i] = (sum_1[i-1] + inv[i]) % mod;
sum_2[i] = (sum_2[i-1] + (1ll*inv[i]*inv[i]%mod)) % mod;
}
while(Q_ --) Work();
return 0;
}