题解:qoj15309 Dumb Problem II

ez 题。

题意:定义 \(f(p)\) 为排列 \(p\) 中前缀极大值的下标,\(g(p)\) 是排列中前缀极大值的值,现在给定 \(n,k\),问现在有 \(k\) 个任意排列,期望会出现多少种不同的 \(g(p)\)\(n,k\le 5000\)

做法:

\(g(p)\) 看起来很难刻画,实则很简单。我们注意 \(g(p)=f(p^{-1})\),而 \(p\) 是任意排列,所以出现多少种 \(g\) 和多少种 \(f\) 是本质一样的。

那么考虑,给定一种 \(f\) 出现的概率。我们从前往后填排列,对于在 \(f\) 里出现的位置 \(i\),那么就要求比前面的数都要大,概率为 \(\frac{1}{i}\),否则为 \(\frac{i-1}{i}\)。那么概率就是全部乘在一起。

那么如何统计答案呢?我们考虑枚举这个排列出现在哪些中,设出现在 \(t\) 个中,用一个组合数算贡献,此时合法的 \(f\) 贡献应为 \(\prod\limits_{i=1}^n((\frac{1}{i})^t+(\frac{i-1}{i})^t)\),这是因为我们要求这 \(t\) 个排列的情况都要一样即可,不在乎一定要不要在 \(f\) 中。

但是注意,因为我们是钦定出现在这些位置,但是也有可能在更多的地方出现了,需要容斥,总的柿子就是:

\[\sum_{t=1}^k(-1)^{t-1}\binom{k}{t}\prod\limits_{i=1}^n((\frac{1}{i})^t+(\frac{i-1}{i})^t) \]

代码非常好写:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 5005, mod = 998244353;
int n, k, inv[maxn], v1[maxn], v2[maxn];
signed main() {
	cin >> n >> k;
	inv[0] = inv[1] = 1;
	for (int i = 2; i <= max(n, k); i++)
		inv[i] = (mod - mod / i) * inv[mod % i] % mod;
	for (int i = 1; i <= n; i++) 
		v1[i] = inv[i], v2[i] = (i - 1) * inv[i] % mod;
	int ans = 0, nw = 1;
	for (int i = 1; i <= k; i++) {
		int res = 1;
		nw = nw * (k - i + 1) % mod * inv[i] % mod;
	//	cout << nw << endl;
		for (int j = 1; j <= n; j++) {
			res = res * (v1[j] + v2[j]) % mod;
			v1[j] = v1[j] * inv[j] % mod;
			v2[j] = v2[j] * (j - 1) % mod * inv[j] % mod;
		}
		ans = (ans + (i & 1 ? 1 : mod - 1) * res % mod * nw) % mod;
	}
	cout << ans << endl;
	return 0;
}
posted @ 2025-12-17 09:58  LUlululu1616  阅读(2)  评论(0)    收藏  举报