Codeforces Round #829 (Div. 2) E(不会概率,输)

题目
题意: 给你一个长度为 n 的 01序列,每次等概率随机交换序列中的一对数,如果它们是逆序对,则交换它们的位置,求排成顺序序列的期望操作次数。
思路: 最后的结果一定是0000011111这样,否则还有逆序对的。假设0的个数是cnt0,1的个数是cnt1。如果前cnt0个位置存在1,就说明他要交换掉。假设这个数量是k,说明最后边还有k个0和他们对应,都没有放到正确的位置。所有的选择方案是Cn2,其中有k*k的可能性选中一对能消去逆序对的。求和i从1到k,每次求选中一对能消去逆序对的两个位置的期望。可以发现是几何分布,前i-1次失败且第i次成功的概率,E(X) = 1/p,也就 i / Cn2的倒数,之后从1到k分别求和即可。
在这里插入图片描述
图片来自这位大佬的博客连接

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,k,T;
const int mod = 998244353;
ll qpow(ll a,int k)
{
	ll res = 1;
	while(k)
	{
		if(k&1) res = res * a % mod;
		a = a * a % mod;
		k >>= 1;
	}
	return res;
}
ll ni(ll x)
{
	return qpow(x,mod-2);
}
void solve()
{
	cin>>n;
	int cnt0 = 0,cnt1 = 0;
	vector<int> a(n);
	for(int i=0;i<n;++i) 
	{
		cin>>a[i];
		if(!a[i]) cnt0++;
	}
	for(int i=0;i<cnt0;++i)
	{
		if(a[i]) cnt1++; //多少对不匹配 
	}
	ll cc = 1ll*n*(n-1)/2; cc %= mod;
	ll fenmu = ni(cc);
	ll ans = 0;
	for(int i=1;i<=cnt1;++i)
	{
		ll tmp = 1ll*i*i%mod*fenmu%mod;
		tmp = ni(tmp);
		ans = (ans + tmp) % mod;
	}
	cout<<ans<<"\n";
}
signed main(void)
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cin>>T;
	while(T--)
	solve();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值