[计数] P6046 纯粹容器
posted on 2024-05-23 08:13:51 | under | source
数据才 \(n\le 50\),就肯定有小彩笔暴力乱搞。
比如我。
唯一难点是转化。将其视作一条链,每次选一条边。单调栈求出左边、右边第一个 \(\ge a_i\) 的 \(lst_i,nxt_i\)。那么 \(i\) 不被淘汰,等价于 \(lst_i\to i\) 这条链的边不被全选,并且 \(i\to nxt_i\) 也不被全选。
然后钦定两条链其中一条被全选,设它有 \(x\) 条边并被全选,另一条链有 \(Y\) 条边选 \(y\) 条,链外选了 \(k\) 条。
那么这样选的方案数 \(res\) 为:
\[res=C(Y,y)C(n-1-x-Y,k)\times x(x+y+k-1)!
\]
解释下这个式子。第一部分表示选边(不考虑顺序);第二部分表示拎出一条边作为最后被选的,并确定其它边的选择顺序。
那么对答案贡献就是:\((x+y+k-1)\times \frac{res}{A(n-1,x+y+k)}\)。
然后枚举即可。复杂度 \(O(n^3)\)。
代码
勤取模。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e2 + 5, mod = 998244353;
int n, a[N], st[N], tp, pre[N], nxt[N], jc[N], jcinv[N];
inline int qstp(int a, int k) {int res = 1; for(; k; a = a * a % mod, k >>= 1) if(k & 1) res = res * a % mod; return res;}
inline void init() {jc[0] = jcinv[0] = 1; for(int i = 1; i < N; ++i) jcinv[i] = qstp(jc[i] = jc[i - 1] * i % mod, mod - 2);}
inline int C(int n, int m) {return n < m ? 0 : jc[n] * jcinv[n - m] % mod * jcinv[m] % mod;}
inline int A(int n, int m) {return n < m ? 0 : jc[n] * jcinv[n - m] % mod;}
signed main(){
init();
cin >> n;
for(int i = 1; i <= n; ++i){
scanf("%lld", &a[i]);
while(tp && a[st[tp]] <= a[i]) --tp;
pre[i] = st[tp], st[++tp] = i;
}
tp = 0;
for(int i = n; i; --i){
while(tp && a[st[tp]] <= a[i]) --tp;
nxt[i] = st[tp], st[++tp] = i;
}
for(int i = 1; i <= n; ++i){
if(!pre[i] && !nxt[i]) {printf("%lld ", n - 1); continue;}
if(!pre[i]) pre[i] = i; if(!nxt[i]) nxt[i] = i;
int res, ress = 0, c1 = i - pre[i], c2 = nxt[i] - i;
if(c1)
for(int j1 = c1; j1 <= c1; ++j1)
for(int j2 = 0; j2 <= max(0ll, c2 - 1); ++j2)
for(int k = 0; j1 + j2 + k <= n - 1; ++k){
res = C(c2, j2) * C(n - 1 - c1 - c2, k) % mod * j1 % mod * jc[j1 + j2 + k - 1] % mod;
ress = (ress + (j1 + j2 + k - 1) * res % mod * qstp(A(n - 1, j1 + j2 + k), mod - 2) % mod) % mod;
}
if(c2)
for(int j1 = 0; j1 <= max(0ll, c1 - 1); ++j1)
for(int j2 = c2; j2 <= c2; ++j2)
for(int k = 0; j1 + j2 + k <= n - 1; ++k){
res = C(c1, j1) * C(n - 1 - c1 - c2, k) % mod * j2 % mod * jc[j1 + j2 + k - 1] % mod;
ress = (ress + (j1 + j2 + k - 1) * res % mod * qstp(A(n - 1, j1 + j2 + k), mod - 2) % mod) % mod;
}
printf("%lld ", ress);
}
return 0;
}

浙公网安备 33010602011771号