[计数] 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;
}
posted @ 2026-01-12 20:14  Zwi  阅读(2)  评论(0)    收藏  举报