Loading

P6046 纯粹容器 数学期望

P6046 纯粹容器 数学期望

链接

其实如果把这个题看做数学题会比较好做一些。稍微分析一下就做出来了。

那么我们来看一下这道题。通常来说,关于概率期望我们先想 dp ,但这个题明显没有给我们一个好的设计状态的思路,我们考虑用数学的方法来做。

\(f_j\) 为容器 \(i\) 在第 \(j\) 轮被干掉的概率。我们对所有的 \(i\) 都求一个:

\[E=\sum\limits_{i=1}^nf_i\times (i-1) \]

就是答案。

我们考虑 \(f_j\) 怎么求,直接求解是比较难的。这个时候我们通常考虑容斥。

\(p_j\) 表示容器 \(i\) 在前 \(j\) 轮被干掉的概率是多少,那么根据容斥,我们有:

\[f_j=p_j-p_{j-1} \]

我们考虑如何求解 \(p_j\)

我们记 \(l\) 为容器 \(i\) 左边第一个比它大的位置,\(r\) 为容器 \(i\) 右边第一个比它大的位置。

显然,如果容器 \(i\) 被干掉,一定是 \(l\)\(i\) 之间或是 \(i\)\(r\) 之间的容器全部被干掉了。我们并不用管 \(l\) 左边和 \(r\) 右边,因为如果 \(l\)\(r\) 被干掉一定是被比他大的容器干掉。

先算 \(i\) 被左边在 \(j\) 轮内被干掉的概率 :

\[g=\frac{\binom{n-1-(i-l)}{j-(i-l)}}{\binom{n-1}{j}} \]

同理,我们可以算出它被右边干掉的概率:

\[\frac{\binom{n-1-(r-i)}{j-(r-i)}}{\binom{n-1}{j}} \]

这里我们把两边都过来的概率算重了,所以我们减去两边都过来的概率:

\[\frac{\binom{n-1-(r-i)-(i-l)}{j-(r-i)-(i-l)}}{\binom{n-1}{j}} \]

注意,我们需要判断上面的概率是否合法。

代码:

#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define int long long
#define uint unsigned int
#define ull unsigned long long
#define N 51
#define M number
using namespace std;

const int INF=0x3f3f3f3f;
const ll mod=998244353;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

int c[N][N];

inline void prework(){
    for(int i=0;i<=50;i++){
        for(int j=0;j<=i;j++){
            if(j==0||j==i) c[i][j]=1;
            else c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
        }
    }
}

int n,a[N];

inline ll ksm(ll a,ll b,ll mod){
    ll res=1;
    while(b){
        if(b&1) (res*=a)%=mod;
        a=a*a%mod;
        b>>=1; 
    }
    return res;
}

inline ll inv(ll a,ll mod){
    return ksm(a,mod-2,mod);
}

ll ans,p[N];

signed main(){
    prework();
    read(n);for(int i=1;i<=n;i++) read(a[i]);
    for(int i=1;i<=n;i++){
        int l=i,r=i;
        for(int j=i-1;j>=1;j--) if(a[j]>a[l]){l=j;break;}
        for(int j=i+1;j<=n;j++) if(a[j]>a[r]){r=j;break;}
        if(r==i&&l==i) {printf("%lld ",n-1);continue;}
        for(int j=1;j<=n-1;j++){
            ll nowans=0,p1=0,p2=0,p3=0;
            if(l!=i&&j>=i-l) p1=c[n-1-(i-l)][j-(i-l)]*inv(c[n-1][j],mod)%mod;
            if(r!=i&&j>=r-i) p2=c[n-1-(r-i)][j-(r-i)]*inv(c[n-1][j],mod)%mod;
            if(l!=i&&r!=i&&j>=(i-l)+(r-i)) p3=c[n-1-(i-l)-(r-i)][j-(i-l)-(r-i)]*inv(c[n-1][j],mod)%mod;
            nowans=p1+p2-p3;p[j]=(nowans%mod+mod)%mod;
            ans+=(p[j]-p[j-1])*(j-1)%mod;ans=(ans%mod+mod)%mod;
        }
        printf("%lld ",ans);ans=0;
    }
    return 0;
}
posted @ 2021-07-10 10:20  hyl天梦  阅读(45)  评论(0编辑  收藏  举报