当前位置: 首页 > news >正文

CSP-S2025 T4 员工招聘 题解

  • 题意简述:

    有个 01 序列 s,1 表示这一位会做 1 的贡献,0 表示这一位不会做贡献,我们需要对另一个序列 c 进行重拍,当一个位置 i,它的 \(c_i \leq 前面未做贡献的位数\) 时,这一位将不会做贡献,我们需要对于合法的 c 计数。一个序列 c 合法当且仅当 \(贡献和 \ge m\)

  • 思路启发:

    注意到前面的位做出的决策会直接影响后面的位的贡献,所以考虑动态规划,且一定要把当前 做贡献/未做贡献 的位数记录在状态里,方便转移。尝试设出状态 \(f_{i, j}\) 表示考虑到第 i 位,有 j 位没有做贡献的方案数,但是我们发现,当我们下一位填一个 \(c \le j\) 时是好转移的,转移到 \(f_{i + 1, j + 1}\) 即可,但是当下一位填 \(c > j\) 时就显得难以转移,因为我们无法确定选的是哪一个 c,从而无法确定下一个 j 转移时是否存在 \(c > j\),这时我们可以考虑贡献延后计算,当加入一个 \(c \le j\) 时直接转移,而加入一个 \(c > j\) 时忽略选数对我们带来的影响,这些影响会在以后的第一个 j,使得 \(c \le j\),即当 \(j = c\) 时,在考虑它带来的方案数。

  • 状态设计:

    \(f_{i, j, k}\) 表示考虑到第 i 位,有 j 位没有做贡献,前 i 位填的 c 里有 k 个 c 小于当前的 j。

  • 转移设计:

    此时我们设 \(cnt_i = \sum_{j = 1}^{n}[c_j = i],sum_i = \sum_{i = 0}^{n} cnt_i\)
    考虑第 i+1 位填什么:

    \(1^\circ\ s_{i + 1} = 1\)
    \(\ \ \ 1.\) 第 i+1 位填一个 \(c > j\),则 \(f_{i + 1, j, k} \leftarrow [n - sum_j > i - k]\ f_{i, j, k}\)
    \(\ \ \ 2.\) 第 i+1 位填一个 \(c \ge j\),则此时第 i+1 位不会产生贡献,j 将会变成 j+1,所以我们需要对 c=j+1 计算它在前 i 位中的贡献,此时枚举前 i 位中有 t 个 c=j,则有 \(f_{i + 1, j + 1, k + t} \leftarrow (sum_j - k) \times t! \times \binom{i-k}{t} \times \binom{{cnt_{j + 1}}}{t} \times f_{i, j, k}\)

    \(2^\circ\ s_{i + 1} = 0\),此时 j 一定会变成 j+1,则再分讨 c 与 j 的关系意义不大,此时可以直接分讨 c 与 j+1 的关系,这样就可以快速得出需要被统计贡献的数的个数,当然讨论 j,然后分别转移显然也是对的。
    \(\ \ \ 1.\) 第 i+1 位填一个 \(c > j+1\),则 \(f_{i + 1, j + 1, k +t} \leftarrow [n - sum_{j + 1} > i - k - t] \times t! \times \binom{i-k}{t} \times \binom{{cnt_{j + 1}}}{t} \times f_{i, j, k}\)
    \(\ \ \ 2.\) 第 i+1 位填一个 \(c \le j+1\),则 $f_{i + 1, j + 1, k + t} \leftarrow (sum_{j + 1} - k - t) \times t! \times \binom{i - k}{t} \times \binom{cnt_{j + 1}}{t} \times f_{i, j, k} $ (这里 \(sum_{j + 1}\) 需要减 t 的原因是这里我们要算的是可以填在第 i+1 位的 c 的个数,而这里的 t 是填在前 i 位的,所以要减去)

  • 代码展示:

#include "bits/stdc++.h"
//#include "bits/extc++.h"
#define ll long long
#define int long long
#define pii std::pair<int, int> 
#define piii std::pair<int, std::pair<int, int> >
#define tiii tuple<int, int, int>
#define mkp std::make_pair
#define smin(a, b) (a = min(a, b))
#define smax(a, b) (a = max(a, b))
#define eb emplace_back
#define pb push_back
#define fi first
#define se second
#define INF ((int)1e9)
#define oo (1e18)
#define debug() printf("Skmqwq")
#define rep(i, j, k) for (int i = (j); i <= (k); ++i)
#define per(i, j, k) for (int i = (j); i >= (k); --i)
using namespace std;
//using namespace __gnu_pbds;
mt19937_64 Skmqwq(time(0) ^ clock());const int N = 5e2 + 7, P = 998244353;
int n, m, c[N], cnt[N], sum[N], f[2][N][N];
int fac[N], ifac[N], inv[N];
string s;inline int qp(int a, int b) {int ret = 1;while (b) {if (b & 1) ret = ret * a % P;a = a * a % P, b >>= 1;}return ret;
}
inline void init() {fac[0] = 1;rep(i, 1, n) fac[i] = fac[i - 1] * i % P;ifac[n] = qp(fac[n], P - 2);per(i, n, 1) ifac[i - 1] = ifac[i] * i % P;rep(i, 1, n) inv[i] = ifac[i] * fac[i - 1] % P;
}
inline int C(int n, int m) { return fac[n] * ifac[m] % P * ifac[n - m] % P; }
inline int A(int n, int m) { return fac[n] * ifac[n - m] % P; }
inline void add(int &a, int b) { a += b;if (a > P) a -= P;
}signed main() {std::ios::sync_with_stdio(false);   std::cin.tie(0);std::cout.tie(0);cin >> n >> m >> s, s = ' ' + s;init();rep(i, 1, n) cin >> c[i], cnt[c[i]]++;sum[0] = cnt[0];rep(i, 1, n) sum[i] = sum[i - 1] + cnt[i];f[0][0][0] = 1;rep(cur, 0, n - 1) {int i = cur & 1, ii = i^1;rep(j, 0, cur) rep(k, 0, min(cur, sum[j])) f[ii][j][k] = 0;rep(j, 0, cur) rep(k, 0, min(cur, sum[j])) {if (s[cur + 1] == '1') {add(f[ii][j][k], (int)((n - sum[j]) > (cur - k)) * f[i][j][k]);rep(t, 0, min(cur - k, cnt[j + 1])) add(f[ii][j + 1][k + 1 + t], (sum[j] - k) * A(cur - k, t) % P * C(cnt[j + 1], t) % P * f[i][j][k] % P);} else {rep(t, 0, min(cur - k, cnt[j + 1])) {add(f[ii][j + 1][k + t], (int)(n - sum[j + 1] > cur - k - t) * f[i][j][k] % P * A(cur - k, t) % P * C(cnt[j + 1], t) % P);if (sum[j + 1] - k - t < 0) continue;add(f[ii][j + 1][k + 1 + t], (sum[j + 1] - k - t) * f[i][j][k] % P * A(cur - k, t) % P * C(cnt[j + 1], t) % P);}       }}// if (cur == 1) cout << f[ii][]}int ans = 0;// rep(j, 0, n - m) cout << f[0][j][sum[j]] << ' ';rep(j, 0, n - m) add(ans, fac[n - sum[j]] * f[n & 1][j][sum[j]] % P);cout << ans << '\n';return 0;
}
http://www.gsyq.cn/news/60705.html

相关文章:

  • 2025 GEO优化公司排名权威榜单解读:浙江四家标杆企业凭何突围?
  • 写给0-1岁的初创公司合伙人(101):天使轮与种子轮融资的条件解锁机制
  • Mac Unity 2018.dmg游戏工具 安装步骤 简单易懂教程(附安装包)
  • 102302147傅乐宜作业3
  • 2025中小学生AI学习机选购核心:5大品牌实测,提分才是硬通货!
  • 深入解析:DNS解析原理及工作流程详解
  • 6000 AI Program Topic 3~6
  • 洛谷 P1908:逆序对 ← 树状数组 + 离散化(数组 + sort + STL map)
  • P10977 Cut the Sequence 分析
  • 软件工程学习日志2025.11.25
  • IT外包与勒索软件:英国经济安全面临的技术风险
  • NumPy广播机制深度解析:为什么有时能加,有时报错?
  • STL常用功能
  • Rust 零拷贝技术:从所有权到专业的系统调用的性能优化之道
  • 2025年下半年奖牌/水晶奖杯/奖杯定制/定制厂家口碑推荐榜
  • 低代码平台选型指南:企业避坑指南与核心评估维度
  • IMX6D的LVDS调试
  • 题解:CF1746D Paths on the Tree
  • 解决Windows窗口在屏幕外的问题
  • ai论文工具推荐:助力学术创作效率提升的实用工具
  • 2025年国际发表必备!多语言AI论文写作工具TOP 3 深度测评
  • 外观检测设备有哪些?制造业主流方案及应用解析
  • 光学膜外观缺陷检测设备:技术创新与行业应用动态
  • 睡眠不好吃的益生菌选哪家好?热门产品解析
  • 热力图数据可视化,调研
  • 元聚变科技集团估值:AI与数据要素驱动的企业价值解析
  • 有助于睡眠的益生菌推荐几款,这些口碑品牌值得关注
  • 苏州刑事律所推荐:如何选择专业可靠的法律服务机构
  • 上海值得投资的AI企业:聚焦技术创新与产业赋能潜力
  • 上海有哪些AI企业值得投资?行业潜力机构盘点