AT_arc156_b 题解
I_like_magic · · 题解
这道题其实不难。
我们先把原先
然后,我们观察最终集合
先定义
我们发现,最终集合需要满足对于任意的整数
因此,我们可以枚举
对于当前的
我们可以发现,只要满足 3 段前说明的条件,那么最终的
设
需要注意的是,如果对于某个
代码:
#include<bits/stdc++.h>
#define int long long // 开 long long 是为了防止取模前爆 int
using namespace std;
const int N = 400005, P = 998244353; // 数据范围及模数
int n, k; // 原集合 A 的元素数量及操作个数
bool f[N]; // 标记某数是否存在于原集合
int sum = 0; // 当前枚举到的 m 对应的 W 值
int ans = 0; // 答案
int frac[N]; // 阶乘数组
int ksm(int a, int n) { // 快速幂
if(n == 0) return 1;
if(n == 1) return a % P;
int d = ksm(a, n / 2);
d = d * d % P;
if(n & 1) d = d * a % P;
return d;
}
int inv(int a) { // 逆元
return ksm(a, P - 2); // 不会的可以去看 OI wiki 乘法逆元
}
int C(int n, int m) { // 组合数
return frac[n] * inv(frac[n - m]) % P * inv(frac[m]) % P; // 计算组合数
}
signed main() {
cin >> n >> k;
frac[0] = 1;
for(int i = 1; i <= n + k; i ++) frac[i] = frac[i - 1] * i % P;
for(int i = 1; i <= n; i ++) {
int a;
cin >> a;
f[a] = 1; // 标记 a 存在于原集合 A
}
sum = k;
for(int i = 0; ; i ++) {
if(f[i]) sum ++; // 修改当前的 M 值
if(sum < i) break; // 无法满足条件
if(f[i + 1]) continue; // 无需统计
ans += C(sum - 1, i); // 将贡献加入答案
ans %= P; // 对 P 取模
}
printf("%d\n", ans); // 输出答案
return 0;
}