题解 P6059 【纯粹容器 senpai】
显然, 我们可以把每个容器的期望转化成下面这个柿子:
其中
现在考虑如何计算
(如果有的话)记在容器
再来看题意,题目中的操作相当于对一条链随机选一条边进行收缩,可以发现
怎么感觉写得特别啰嗦
复杂度
代码:
#include<cstdio>
using namespace std;
typedef long long ll;
const ll mod = 998244353;
const int MAXN = 60;
int a[MAXN], ld[MAXN], rd[MAXN];
ll C[MAXN][MAXN];
inline ll fpow(ll a, ll b){
ll res = 1;
while (b){
if (b & 1)
res = res * a % mod;
a = a * a % mod, b >>= 1;
}
return res;
}
inline ll inv(ll a){return fpow(a, mod - 2);}
int main(){
int N;
scanf("%d", &N);
for (int i = 1; i <= N; ++i)
scanf("%d", &a[i]);
for (int i = 1; i <= N; ++i){
for (int j = i - 1; j >= 1; --j)
if (a[j] > a[i]){
ld[i] = i - j;
break;
}
for (int j = i + 1; j <= N; ++j)
if (a[j] > a[i]){
rd[i] = j - i;
break;
}
}
C[0][0] = 1;
for (int i = 1; i <= N; ++i){
C[i][0] = 1;
for (int j = 1; j <= i; ++j)
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
}
ll tmp, pa, pb, pab;
for (int i = 1; i <= N; ++i){
tmp = 0;
for (int j = 1; j < N; ++j){
pa = pb = pab = 0;
if (ld[i] && j - ld[i] >= 0)
pa = C[N - 1 - ld[i]][j - ld[i]] * inv(C[N - 1][j]) % mod;
if (rd[i] && j - rd[i] >= 0)
pb = C[N - 1 - rd[i]][j - rd[i]] * inv(C[N - 1][j]) % mod;
if (ld[i] && rd[i] && j - ld[i] - rd[i] >= 0)
pab = C[N - 1 - ld[i] - rd[i]][j - ld[i] - rd[i]] * inv(C[N - 1][j]) % mod;
tmp = (tmp + 1 + mod - pa + mod - pb + pab) % mod;
}
printf("%lld ", tmp);
}
return 0;
}