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;
}