Description
冒泡排序的交换次数被定义为交换过程的执行次数。
小 S 开始专注于研究⻓度为 n 的排列,他想知道,在你运气足够好的情况下(即每次冒泡排序的交换次数都是可能的最少交换次数,仿佛有上帝之手在操控),对于一个等概率随机的长度为n 的排列,进行这样的冒泡排序的期望交换次数是多少?
Solution
ION的梗玩到现在真是
一开始看到那两个rand还以为不可做。。。可啪
由于题目告诉我们交换次数一定最小,考虑怎么求一个排列的最小交换次数。我们把每个数字和下标连边,记形成环的数量为s,一个环内最小交换次数为size-1,可知总的交换次数最小为n-s
现在考虑怎么求环的期望数量。我们令f[i]为i个数排列形成环的期望数量,显然有f[i]=f[i-1]+w,其中w是i形成新的环的概率。可以发现i只有放在位置i会自成一个环,因此答案为
∑
i
=
1
n
1
i
\sum\limits_{i=1}^n \frac{1}{i}
i=1∑ni1
然后就线性求个逆元前缀和就没了。。
Code
#include <stdio.h>
#include <string.h>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
typedef long long LL;
const int MOD=998244353;
const int N=10000005;
LL inv[N],s[N];
int main(void) {
freopen("inverse.in","r",stdin);
freopen("inverse.out","w",stdout);
inv[1]=s[1]=1;
rep(i,2,N-1) {
inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
s[i]=s[i-1]+inv[i];
(s[i]>=MOD)?(s[i]-=MOD):0;
}
int T; for (scanf("%d",&T);T--;) {
LL n; scanf("%lld",&n);
LL ans=(n-s[n]+MOD)%MOD;
printf("%lld\n", ans);
}
return 0;
}