minmax容斥 - 2026/8/26 NOIP模拟赛A题
传送门
原题
题目背景
叠甲:本场原题数量多,且很板,有些大佬可能全做过,如果 AK 了不要喷题简单,谢谢!
大 B 是小 N 的粉丝。
题目描述
有 \(n\) 张小 N 的图片。接下来每一天,你会重复 \(k\) 次:等概率独立随机选择一张小 N 的图片,加入大 B 的图库。
请问期望几天结束后,第一次满足大 B 的图库中包含所有小 N 的 \(n\) 张图片?由于你不喜欢小数,你只想知道答案对 \(998244353\) 取模的结果,也即:设答案为 \(\dfrac{P}{Q}\),其中 \((P,Q)=1,\ P,Q\in\mathbb{Z}\),你要输出一个 \(x\) 满足 \(0 \le x < 998244353,\ P - Qx \equiv 0 \pmod{998244353}\)。
形式化题意
给定 \(n,k\)。有一个不可重集 \(S\),初始 \(S=\varnothing\)。接下来每次操作,你重复 \(k\) 次将 \([1,n]\) 的独立等概率随机整数加入 \(S\)。问期望几次操作后,第一次满足 \(|S|=n\)。答案对 \(998244353\) 取模。
注:
\(\forall 1 \le i < n,\ i^k \not\equiv n^k \pmod{998244353}\)。
输入格式
输入包含一行两个整数 \(n,k\),表示小 N 的图片数量与你每天重复加图的次数。
输出格式
输出包含一行一个自然数,表示答案。
输入输出样例
样例 #1
样例输入 #1
3 2
样例输出 #1
573990506
说明/提示
对于所有数据,保证:
- \(1 \le n,k \le 3 \times 10^5\);
- \(\forall 1 \le i < n,\ i^k \not\equiv n^k \pmod{998244353}\)。
子任务
| 子任务编号 | \(n\) 的范围 | \(k\) 的范围 | 分值 |
|---|---|---|---|
| 1 | \(\le 8\) | \(\le 8\) | 1 |
| 2 | \(\le 3\times 10^5\) | \(=1\) | 18 |
| 3 | \(\le 40\) | \(\le 40\) | 31 |
| 4 | \(\le 3000\) | \(\le 3000\) | 10 |
| 5 | \(\le 3\times 10^5\) | \(\le 3\times 10^5\) | 40 |
思路
minmax容斥 的标准形式:对于一个不可重集 \(S\)(若 \(S\) 中有重复元素,通过强制为其规定大小关系可转化为不可重集进行操作)有:
这个式子对于期望形式也是成立的。
对于本题来说,我们先来转化所求:设 \(t_i\) 代表第 \(i\) 张图片期望在第 \(t_i\) 天出现,那么我们可以把所求写为 \(\max\{t_1,t_2,\dots,t_n\}\)。
运用 minmax容斥:
由于图片之间没有差别,我们通过对称性得到,对于一个大小为 \(m\) 的 \(T\in S\),其最小值代表的是 \(T\) 中出现最早的元素,这个事情是十分容易搞出来的。
首先,我们知道,每一次操作(注意不是一天)抽到 \(T\) 中元素的概率是 \(\sum_{t_i\in T}p_i=m\times p\),其中 \(p=\frac1n\),故一天抽 \(k\) 次抽中 \(T\) 中元素的概率 \(P_0=1-(\frac {n-m}n)^k\)。我们接下去计算期望多少天可以抽中 \(T\) 中的元素:
令 \(p=\frac {n-m}n\),则
我们将这个结果套到 minmax容斥 的式子里:
AC Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MOD = 998244353;
const int INF = 2e9; // const ll INF = 4e18
const int N = 3e5 + 5;
ll qpow(ll a, ll b) {
ll ret = 1;
while (b) {
if (b & 1) ret = ret * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return ret;
}
ll n, k;
ll ans;
ll fact[N], rev[N];
ll C(int n, int m) {
ll ret = fact[n] * rev[n - m] % MOD;
ret = ret * rev[m] % MOD;
return ret;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> k;
fact[0] = 1;
for (int i = 1; i <= n; ++i) {
fact[i] = fact[i - 1] * i % MOD;
}
rev[n] = qpow(fact[n], MOD - 2);
for (int i = n; i; --i) {
rev[i - 1] = rev[i] * i % MOD;
}
ll f = 1;
for (int i = 1; i <= n; ++i) {
ll tmp = qpow(n, MOD - 2) * (n - i) % MOD;
tmp = (1 - qpow(tmp, k)) % MOD;
if (tmp < 0) tmp += MOD;
tmp = qpow(tmp, MOD - 2);
(ans += f * C(n, i) * tmp) %= MOD;
f *= -1;
}
if (ans < 0) ans += MOD;
cout << ans << '\n';
return 0;
}

浙公网安备 33010602011771号