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

P14364 [CSP-S 2025] 员工招聘

考虑设 \(f_{i, j}\) 为前 \(i\) 个人死了 \(j\) 个,由于不知道哪些人选了所以无法转移。原因是前面的决策会影响后面的决策,所以考虑贡献延后计算。

会发现一个事情,对于当前 \(c_x \leq j\) 的东西之后不会再决策所以对后面是没有影响的,这启发我们在 \(c_x = j\) 的时候结算贡献。

不妨设 \(f_{i, j, k}\),其中 \(k\) 为前面钦定的 \(c_x > j\) 的位置的个数。

转移分三种:

  1. \(s_{i+ 1} = 1\)\(c_x > j\)\(f_{i, j, k} \to f_{i + 1, j, k + 1}\)
  2. \(s_{i + 1} = 0\)\(c_x > j\)\(f_{i, j, k} \times \binom{k + 1}{l} \times \binom{cnt_{j + 1}}{l} \times l! \to f_{i + 1, j + 1, k + 1 - l}\)
  3. \(c_x \leq j\)\(f_{i, j, k} \times \binom{k}{l} \times \binom{cnt_{j + 1}}{l} \times l! \times [pre_j - (i - k)] \to f_{i + 1, j + 1, k - l}\)

其中 \(pre\)\(cnt\) 分别是 \(\leq j\)\(= j\) 的数量。

答案考虑枚举死了多少人,即 \(\sum_{i = 0}^{n - m} f_{n, i, n - pre_i} (n - pre_i)!\)

注意到 \(l\) 的总和不超过 \(n\),所以是 \(O(n^3)\) 的。

我们做完了,主要思路就是找到难做的地方消除这个难点。

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = (a); i <= (b); i ++)
#define fro(i, a, b) for (int i = (a); i >= b; i --)
#define INF 0x3f3f3f3f
#define eps 1e-6
#define lowbit(x) (x & (-x))
#define reg register
#define IL inline
typedef long long LL;
typedef std::pair<int, int> PII;
inline int read() {int x = 0, f = 1;char ch = getchar();while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); }return x * f;
}
// mt19937_64 sj(chrono::steady_clock::now().time_since_epoch().count());
// uniform_int_distribution<LL> u0(0, 1ll << 60);const int N = 510, Mod = 998244353;
int n, m, c[N], pre[N], cnt[N];
int C[N][N], fac[N];
int f[2][N][N];
char s[N];IL int add(int &a, int b) {return a = (a + b) % Mod;
}void init() {for (int i = 0; i <= n; i ++) {C[i][0] = 1;for (int j = 1; j <= i; j ++) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % Mod;}fac[0] = 1;for (int i = 1; i <= n; i ++) fac[i] = 1ll * fac[i - 1] * i % Mod;
}int main() {n = read(), m = read();scanf("%s", s + 1);for (int i = 1; i <= n; i ++) c[i] = read(), cnt[c[i]] ++;pre[0] = cnt[0];for (int i = 1; i <= n; i ++) pre[i] = pre[i - 1] + cnt[i];init();f[0][0][0] = 1;for (int i = 0; i < n; i ++) {for (int j = 0; j <= i; j ++) {for (int k = 0; k <= i; k ++) {if (!f[i & 1][j][k]) continue;if (s[i + 1] == '1') add(f[i + 1 & 1][j][k + 1], f[i & 1][j][k]);if (s[i + 1] == '0') {for (int l = 0; l <= min(cnt[j + 1], k + 1); l ++) {int g = 1ll * C[k + 1][l] * C[cnt[j + 1]][l] % Mod * fac[l] % Mod;add(f[i + 1 & 1][j + 1][k + 1 - l], 1ll * f[i & 1][j][k] * g % Mod);}}if (pre[j] - (i - k) < 0) continue; for (int l = 0; l <= min(cnt[j + 1], k); l ++) {int g = 1ll * C[k][l] * C[cnt[j + 1]][l] % Mod * fac[l] % Mod * (pre[j] - (i - k)) % Mod;add(f[i + 1 & 1][j + 1][k - l], 1ll * f[i & 1][j][k] * g % Mod);}            }}memset(f[i & 1], 0, sizeof f[i & 1]);}int ans = 0;for (int i = 0; i <= n - m; i ++) ans = add(ans, 1ll * f[n & 1][i][n - pre[i]] * fac[n - pre[i]] % Mod);printf("%d\n", ans);return 0;
}
http://www.zskr.cn/news/47955.html

相关文章:

  • 完整教程:【RabbitMQ】架构原理、消息丢失、重复消费、顺序消费、事务消息
  • List执行Dispose时可释放子元素逻辑占用的List写法
  • 值得复习的题目
  • 找唯一特征去重转移DP——CF1210F2 Marek and Matching
  • 固体废物资源化处理简答题与论述题
  • 详细介绍:Python基础语法与数据类型详解
  • 第23天(简单题中等题 二分查找)
  • Cinema4D 2025保姆级下载安装教程|含安装包获取+新手入门指南
  • CF2101D
  • 01321:棋盘问题
  • C 变量的作用域与生存周期
  • #题解#洛谷P1496#离散化#
  • 20251112 正睿
  • 如何根据色带计算电阻阻值
  • 《云操作系统(OpenStack)第二版》学习笔记汇总版-从0开始完成在线安装并为离线安装准备软件包
  • Day36(6)-F:\硕士阶段\Java\课程代码\后端\web-ai-code\web-ai-project01
  • 2025 11 12
  • Total Recall: 如何在Windows下开发输入法
  • 大数据量场景下的编辑 / 选择 / 详情优化
  • RabbitMQ相关
  • 使用NVIDIA TAO 6和DeepStream 8构建实时视觉检测管道 - 实践
  • ChatBI 重构工业数据交互:TDengine IDMP 让数据对话更智能
  • 云服务模式进化论:企业云战略的致命误区,从IaaS到FaaS的死亡之旅!
  • Python 实现对遥感影像根据DN值上色
  • 【免费】MySQL自动化运维工具,一键生成WORD和EXCEL
  • 实用指南:轻量化 + 绿色部署的日志监控系统log-monitor设计思路(一)
  • 随机链表的复制-leetcode
  • useActionState 阻止表单重置
  • 部署MQTT Broker - Mosquitto - -YADA
  • 7年java开发的一些感悟