给你一个01串,给你一个操作让你把这个01串排序的期望是多少
操作:选(i,j)中i<j其中ai>aj可以交换这两个数
分析:
不管怎么操作,最后的结果都是000..0011..11这样的,所以找到全部的0,前面的k个都是0。所以枚举一下前面k个,看看有几个1,假设有m个1,这个时候就需要交换了。前面有m个1,后面必然有m个0与之和前面的1进行交换。每次选两个那就是.然后选择有m*m个
所以概率就是,那期望就是
那每个期望相加,就是,这个时候就是需要使用乘法逆元了:
等价于,这个时候就是求b的逆元:
具体看代码:
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define IOS ios::sync_with_stdio(false), cin.tie(0);
#include<iostream>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>
#include<cmath>
#include<queue>
#include<deque>
using namespace std;
#define int long long
typedef long long ll;
typedef pair<int,int> PAII;
const int N=2e6+10,M=5050,INF=1e18,mod=998244353;
int a[N];
int qmi(int a, int b)
{
int res = 1;
while (b)
{
if (b & 1) res = res * a%mod;
a = a * a%mod;
b >>= 1;
}
return res;
}
signed main(){
IOS;
int T;
//T=1;
cin>>T;
while(T--)
{
int n;
cin>>n;
int cnt=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]==0) cnt++;
}
int k=0;
for(int i=1;i<=cnt;i++)
if(a[i]==1) k++;
int res=0;
for(int i=1;i<=k;i++)
{
res=(res+n*(n-1)/2%mod*qmi(i*i%mod,mod-2)%mod)%mod;
}
cout<<res<<"\n";
}
return 0;
}
/*
*/