jzoj5931 冒泡排序

11 篇文章 0 订阅

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=1ni1
然后就线性求个逆元前缀和就没了。。

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值