【数学期望】Codeforces#829 Div1 C.Wish I Knew How to Sort

https://codeforces.com/contest/1753/problem/C

题目描述

给你一个长度为 n n n 01 01 01 序列,每次等概率随机交换序列中的一对数,如果它们是逆序对,则交换它们的位置,求排成顺序序列的期望操作次数。

Solution

t u t o r i a l tutorial tutorial 给出的是一个 D P DP DP 做法,这里说一下另一种从代码上来看很神仙的做法。

假设原序列为 [ 1010111001 ] [1010111001] [1010111001],排序后为 [ 0000111111 ] [0000111111] [0000111111],从形式上看等价于将最前的两个 1 1 1 与最后两个0做交换就完成了,其实实际上也是这样?做一个不严谨的说明:交换 a 3 a 4 a_3 a_4 a3a4 后序列为: [ 1001111001 ] [1001111001] [1001111001],这种交换其实是没有贡献的交换,将最后的0替换掉的交换才是“有效”交换。

于是大胆猜测柿子为 ∑ j = 1 m ∑ i = 1 ∞ i ∗ j 2 ( n 2 ) ∗ ( 1 − j 2 ( n 2 ) ) i − 1 \sum_{j=1}^m {\sum_{i=1}^\infty i*\frac {j^2} {\tbinom{n}{2}}*(1-\frac {j^2} {\tbinom{n}{2}})^{i-1}} j=1mi=1i(2n)j2(1(2n)j2)i1解释一下:其中 m m m 为原序列中未归位 1 1 1 的数量,目前还有 j j j 1 1 1 未归位时,想实现一次“有效”交换,必须要选择一个末尾 0 0 0 和未归位 1 1 1 进行交换才可以,这两种数量都是 j j j,所以概率为 j 2 ( n 2 ) \frac {j^2} {\tbinom{n}{2}} (2n)j2,然后就可推出上述柿子。
于是就可以用小学二年级知识开心的对上述柿子进行化简得到 a n s = ( n 2 ) ∗ ∑ i = 1 m 1 i 2 ans = \tbinom{n}{2} * \sum_{i=1}^m {\frac 1 {i^2}} ans=(2n)i=1mi21

Code

#include<bits/stdc++.h>
using namespace std;

#define int long long
const int mod = 998244353;
int ksm(int a, int b){
    int res = 1;
    while (b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res%mod;
}
int n;
signed main(){
    int t;
    cin >> t;
    while (t--){
        int n;
        cin >> n;
        vector<int> a(n+1), b(n+1);
        for (int i=1; i<=n; i++) {
            cin >> a[i];
            b[i] = a[i];
        }
        sort(b.begin(), b.end());
        int m = 0;
        for (int i=n; b[i]==1; i--) {
            if(a[i]!=b[i]) m++;
        } //统计未归位1个数
        int res = 0;
        for (int i=1; i<=m; i++) {
            res += ksm(i,mod-2) * ksm(i,mod-2) % mod;
            res %= mod;
        }
        cout << res * n % mod * (n-1) % mod * ksm(2ll,mod-2) % mod << '\n';
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值