CF1096F Inversion Expectation [期望]

本文探讨了在一个包含不确定位置的排列中,如何计算所有可能排列的逆序对期望数量,并给出了具体的算法实现,包括树状数组的应用和概率计算。

题意

  给你一个长为$n$的排列,若某一位为$−1$则这一位是不确定的。每种可能的排列出现的概率相等。求期望逆序对数对$998244353$取模的结果。


分类讨论一下:

  1. 已知位置之间贡献:树状数组计算

  2.未知位置之间贡献:$\frac{\tbinom{m}{2}}{2}=\frac{1}{4}m(m-1)$ ($m$为未知位置个数)

  3.已知和未知之间贡献:

    对于每个未知的位置,取不同值时前面比它大和后面比它小的数的个数。

    转化一下就是:每个已知的位置贡献为$$(前面未知位置个数\times比这个数大的未使用的数的个数+后面未知位置个数\times比这个数小的未使用的数的个数)\times m^{-1}$$

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long ll;
 6 const int N=200010;
 7 const ll P=998244353;
 8 ll n,a[N],app[N],b[N],m,c[N],inv,S;
 9 ll ans;
10 inline void add(int x) {for (; x<=n; x+=(x&-x)) c[x]++;}
11 inline ll sum(int x) {ll s=0; for (; x; x-=(x&-x)) s+=c[x]; return s;}
12 inline ll pow(ll x,ll k) {ll r=1; for (; k; k>>=1,x=x*x%P) if (k&1) r=r*x%P; return r;}
13 int main() {
14     scanf("%lld",&n);
15     for (int i=1; i<=n; i++) {scanf("%lld",&a[i]),m+=(a[i]==-1); if (~a[i]) app[a[i]]=1;}
16     for (int i=1; i<=n; i++) {
17         b[i]=b[i-1]+(app[i]^1);
18         if (~a[i]) {
19             ans+=sum(n)-sum(a[i]);
20             add(a[i]);
21         }
22     }
23     ans=(ans%P)+1ll*m*(m-1)%P*748683265ll%P; //4^-1
24     inv=pow(m,P-2); S=0;
25     for (int i=1; i<=n; i++) {
26         if (~a[i]) S+=b[a[i]];
27         else ans=(ans+1ll*S*inv%P)%P;
28     }
29     S=0;
30     for (int i=n; i; i--) {
31         if (~a[i]) S+=m-b[a[i]];
32         else ans=(ans+1ll*S*inv%P)%P;
33     }
34     printf("%lld\n",ans);
35     return 0;
36 }

 

转载于:https://www.cnblogs.com/hnooo/p/10207651.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值