[CF1753C]Wish I Knew How to Sort

做题时间:2022.10.25

给定一个长度为 n 的01序列 a 和一种操作,你需要用这种操作将序列从小到大排序。操作为:等概率随机选择两个位置 i,j(i<j),若 ai>aj,则交换 aiaj(当 aiaj,交换失败也算一次操作)

求出执行操作的期望次数,对 998244353 取模

第一行一个整数 T 表示数据组数

每组数据第一行一个整数 n 表示序列长度

接下来一行 n 个整数表示序列 a

对于每组数据,输出一行一个整数表示答案

期望、概率

最终单调不降的目标序列肯定是 00...00111...111,交换过程就是以中间的 01 为分界线,左边的 1 全部移动到右边,右边的 0 全部移动到左边,根据期望线性性质,我们可以单独考虑每一次操作,最后将每次操作的期望值加起来即可。

设当前分界线左边有 i1,则分界线右边会有 i0,交换一次左边的 1 和右边的 0 的概率为:

i2(n2)

而期望是概率的倒数,因此最终我们要求的便是:

i=1k(n2)i2

其中 k 是一开始分界线左边的 1 数量(右边的 0 数量)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+50;
const ll mod=998244353;
int n,a[N],cnt,k,t;
ll Pow(ll a,ll b)
{
ll ans=1ll,base=a%mod;
while(b){
if(b&1) ans*=base,ans%=mod;
base*=base,base%=mod;
b>>=1;
}
return ans;
}
void Wish()
{
cnt=0,k=0;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),cnt+=(a[i]==0);//计算分界线
for(int i=1;i<=cnt;i++){
if(a[i]) k++;
}
ll ans=0;
for(int i=1;i<=k;i++){//计算答案
ans+=1ll*n*(n-1)%mod*Pow(2ll*i*i,mod-2)%mod;
ans%=mod;
}
printf("%lld\n",ans);
}
int main()
{
scanf("%d",&t);
while(t--) Wish();
return 0;
}

本文作者:lxzy

本文链接:https://www.cnblogs.com/Unlimited-Chan/p/16823701.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   lxzy  阅读(125)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.