题目
给一个长度为n(n<=2e5)的01串,每次随机选两个不同的下标(i,j),
若ai>aj,则交换,问序列排成增序的期望次数,答案是一个分数,对998244353取模
实际是t(t<=1e5)组样例,但n的总长不超过2e5
思路来源
官方题解/gzchenben的讲解
题解
感觉是典中典的期望题,但是还是没想到
考虑最终要被换成的序列是形如0001111的,
统计这个序列里有多少个0,设统计到了x个0,
再统计原序列里前x个位置有多少个1,设统计到了y个1,
说明有y对(0,1)不在他们该在的位置,需要后续被归位
dp[i]表示还有i对(0,1)没被归位的期望次数,
在还有i对(0,1)的时候,抽到其中一对(0,1)并归位的概率p为,
①根据转移公式化简得,单步期望步数为1/p
②或者,根据期望的线性性可知,每一步操作的概率互不影响,单步期望步数为1/p
对这i步的期望步数求和即可
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10,mod=998244353;
int a[N],b[N],t,n,cnt,ans,zero,one;
int modpow(int x,int n,int mod){
int res=1;
for(;n;n>>=1,x=1ll*x*x%mod){
if(n&1)res=1ll*res*x%mod;
}
return res;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
cnt=ans=zero=one=0;
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
zero+=(!a[i]);
}
for(int i=1;i<=zero;++i){
one+=a[i];
}
for(int i=1;i<=one;++i){
ans=(ans+modpow(1ll*i*i%mod,mod-2,mod))%mod;
}
ans=1ll*n*(n-1)/2%mod*ans%mod;
printf("%d\n",ans);
}
return 0;
}