*题解:P14364 [CSP-S 2025] 员工招聘 / employ

news/2025/11/8 18:01:56/文章来源:https://www.cnblogs.com/yuyc/p/19202790

原题链接

参考文献

我这篇写的烂,建议看参考文献。

解析

设有 \(x\) 个人未被录用。显然,\(x\) 单调不减,当 \(x\) 变为 \(x + 1\) 时, \(c_i = x + 1\) 的所有人就必定无法被录用了,如果在此时才统计已经面试了的人里 \(c_i=x + 1\) 的人的贡献,就叫做贡献延后计算。

方便起见,令 \(cnt_i\) 表示耐心值 \(c=i\) 的人的个数, \(pre\)\(cnt\) 的前缀和数组。

\(dp_{i,j,k}\) 表示面试了 \(i\) 个人,有 \(j\) 个人未被录取,已经录取了的人中有 \(k\) 个人的 \(c > j\),已经统计了 \(c \le j\) 的人的贡献时的答案。

考虑 \(s_{i + 1}\) 的值。

\(s_{i + 1} =0\),则必定无法录取,这意味着未录取人数必定 \(+1\),也就是说我们需要统计 \(c=j+1\) 的人的贡献。

枚举已经面试过的人中 \(c=j+1\) 的人的个数 \(t\),那么这 \(t\) 个人需要在 \(cnt_{j + 1}\) 个人中选取,有 \(k\) 个位置可以放,这 \(t\) 个人内部也有排列顺序,于是就可以列出转移式:

\[dp_{i,j,k}\binom{cnt_{j +1}}{t}\binom{k}{t}t!\to dp_{i+1,j+1,k-t} \]

但是这实际上还没有考虑第 \(i + 1\) 个人。

若第 \(i + 1\) 个人的耐心值 \(c > j+1\),则暂时不需要计算贡献,但是注意 \(k\) 会增加 \(1\)

\[dp_{i,j,k}\binom{cnt_{j +1}}{t}\binom{k}{t}t!\to dp_{i+1,j+1,k-t+1} \]

否则需要算他的贡献,在 \((pre_{j + 1}-(i-(k-t)))\) 个人中选一个:

\[dp_{i,j,k}\binom{cnt_{j +1}}{t}\binom{k}{t}t!(pre_{j + 1}-(i-(k-t)))\to dp_{i+1,j+1,k-t} \]

\(s_{i + 1}=1\) 的情况同理。

时间复杂度由于要枚举 \(i,j,k,t\),看似是 \(O(n^4)\) 的,可实际上我们可以发现 \(t\) 的上界是 \(cnt_j\),而 \(\sum cnt_j=n\),于是有:

\[ \sum_{i=1}^n \sum_{j=1}^n \sum_{k=1}^n O(cnt_j)=\sum_{i=1}^n \sum_{k=1}^n \sum_{j=1}^n O(cnt_j) =\sum_{i=1}^n \sum_{k=1}^n O(n) =O(n ^ 3)\]

故时间复杂度为 \(O(n^3)\)

代码

/*
设 dp[i][j][k] 表示排列的前 i 个人中,有 j 个未被录用,有 k 个 c > j 时,只考虑 c <= j 的人的贡献的方案数若 s[i] = 0,则必定无法被录用,j 必定 + 1,所以需要加入 c = j + 1 的贡献
设有 t 个 c = j + 1,我们先要看在 c[i] = p + 1 中选出哪 t 个 i,然后在 k 个位置中选 t 个位置放,然后再看这 t 个人内部的排列 
只能在 k 个位置里放是因为别的位置被 c 更小的给占了,
已知有 j 个未被录用的情况下,c > j 的相对顺序我们是不关心的,因为能否被录用只取决于 s 是否为 0 
设 cnt[i] 表示 c 为 i 的个数,pre 为 cnt 的前缀和数组 
dp[i][j][k] * C(cnt[j + 1],t) * C(k,t) * A(t,t) -> dp[i + 1][j + 1][k - t]
还有 p[i + 1] 的贡献没有算
如果 c[p[i + 1]] > j + 1,那么本身就不需要算贡献,贡献留着后面算。
否则需要在 pre[j + 1] 个人里选一个,这之中有 (i - (k - t)) 个已经选过了
于是就变成了 dp[i][j][k] * C(cnt[j + 1],t) * C(k,t) * A(t,t) * (pre[j + 1] - (i - (k - t))) -> dp[i + 1][j + 1][k - t]若 s[i] = 1,则录用情况取决于 c[p[i + 1]] 的大小
若 c[p[i + 1]] > j,贡献不用算,直接转 
dp[i][j][k] -> dp[i + 1][j][k + 1]
若 c[p[i + 1]] <= j,无法录用,同样枚举 t
dp[i][j][k] * C(cnt[j + 1],t) * C(k,t) * (pre[j] - (i - k)) -> dp[i + 1][j + 1][k - t]最后统计答案时需要乘上排列数算一下复杂度,看似是 O(n ^ 4) 由于 sum(cnt[i]) = n,所以实际上是 sum_{i=1}^n sum_{k=1}^n sum_{j=1}^n O(cnt[j]) 
=sum_{i=1}^n sum_{k=1}^n O(n)
=O(n ^ 3)这就是贡献延后计算吗 */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 500 + 5,M = 2e5 + 5,mod = 998244353;
int dp[N][N][N];
int s[N],c[N],cnt[N],pre[N];
int fac[N],C[N][N];
int main(){ios::sync_with_stdio(false);cin.tie(0);fac[0] = 1;for(int i=0;i<N;i++){C[i][0] = 1;}for(int i=1;i<N;i++){fac[i] = 1ll * fac[i - 1] * i % mod;for(int j=1;j<N;j++){C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;}}int n,m;cin>>n>>m;string st;cin>>st;for(int i=0;i<n;i++){s[i + 1] = st[i] - '0';}for(int i=1;i<=n;i++){cin>>c[i];cnt[c[i]]++;}pre[0] = cnt[0];for(int i=1;i<=n;i++){pre[i] = pre[i - 1] + cnt[i];}dp[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(s[i + 1] == 1){if(n - pre[j] - k > 0) dp[i + 1][j][k + 1] = (dp[i + 1][j][k + 1] + dp[i][j][k]) % mod;if(pre[j] - (i - k) > 0){for(int t=0;t<=min(cnt[j + 1],k);t++){dp[i + 1][j + 1][k - t] = (dp[i + 1][j + 1][k - t] + 1ll * dp[i][j][k] * fac[t] % mod * C[k][t] % mod * C[cnt[j + 1]][t] % mod * (pre[j] - (i - k)) % mod) % mod;						}}}else{for(int t=0;t<=min(cnt[j + 1],k);t++){if(n - pre[j + 1] - (k - t) > 0){dp[i + 1][j + 1][k - t + 1] = (dp[i + 1][j + 1][k - t + 1] + 1ll * dp[i][j][k] * fac[t] % mod * C[k][t] % mod * C[cnt[j + 1]][t] % mod) % mod;
//							cout<<"[ "<<i<<" "<<j<<" "<<k<<" ] -> "<<"[ "<<i + 1<<" "<<j + 1<<" "<<k - t + 1<<" ] 1 :"<<dp[i][j][k]<<" "<<dp[i + 1][j + 1][k - t + 1]<<'\n';}if(pre[j + 1] - (i - (k - t)) > 0){dp[i + 1][j + 1][k - t] = (dp[i + 1][j + 1][k - t] + 1ll * dp[i][j][k] * fac[t] % mod * C[k][t] % mod * C[cnt[j + 1]][t] % mod * (pre[j + 1] - (i - (k - t))) % mod) % mod;
//							cout<<"[ "<<i<<" "<<j<<" "<<k<<" ] -> "<<"[ "<<i + 1<<" "<<j + 1<<" "<<k - t<<" ] 2 :"<<dp[i][j][k]<<" "<<dp[i + 1][j + 1][k - t]<<'\n';}						}}}}}
//	cout<<dp[2][1][0]<<'\n';int res = 0;for(int i=0;i<=n - m;i++){
//		cout<<i<<" "<<n - pre[i]<<" "<<dp[n][i][n - pre[i]]<<" "<<fac[n - pre[i]]<<'\n';res = (res + 1ll * dp[n][i][n - pre[i]] * fac[n - pre[i]] % mod) % mod;}cout<<res;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/959889.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MarkDown Day1

MarkDown学习 标题 (空格)标题名字 一级标题 (空格)标题名字 二级标题 (空格)标题名字 三级标题 井号最多到六级 字体 hello,word! 粗体:** 文字 ** hello,word! 斜体:* 文字 * hello,…

逆向基础--C++介绍与环境 (01)

逆向基础--C++介绍与环境 (01)一.介绍1.1 C++ 是一种高级语言,它是由 Bjarne Stroustrup 于 1979 年在贝尔实验室开始设计开发的。C++ 进一步扩充和完善了 C 语言,是一种面向对象的程序设计语言。C++ 可运行于多种平…

【技术术语】静默失效

【技术术语】静默失效“静默失效”(Silent Failure)是指系统或程序在出现错误或故障时,没有给出任何明显的错误提示或警告,而是继续运行,导致问题被掩盖,最终可能引发更严重的后果。这种情况在软件开发、硬件设计…

深入解析:Git Commit Message 最佳实践:从一次指针Bug说起

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年文化节活动篷房订做厂家权威推荐榜单:航空机库篷房/体育篷房/宴会篷房源头厂家精选

在各类文化节庆活动日益丰富的市场环境下,活动篷房以其灵活的空间解决方案,成为保障活动顺利实施的关键设施。行业数据显示,2024年国内篷房市场规模增长率稳定在15%左右,其中针对文化节、展览展示等临时性活动的定…

【技术术语】惊群效应

【技术术语】惊群效应惊群效应 (Thundering Herd Problem) 惊群效应是计算机科学中的一个术语,用来描述当多个进程或线程同时被唤醒去竞争有限资源时导致的性能下降现象。 基本概念 惊群效应得名于动物受惊后群体盲目…

Docker 资源限制与容器管理 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

使用 gitee 完整简要演示 20251108

安装 git 安装步骤 请看: https://www.cnblogs.com/emanlee/p/16296704.html首先在 gitee.com 注册用户; 记住:用户名,email,密码照着这个配置: https://www.cnblogs.com/emanlee/p/18729324Visual Studio Code…

Spide - Personal Blog Magazine WordPress Theme Download - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

【技术术语】即发即弃

【技术术语】即发即弃即发即弃(Fire-and-Forget) 是一种编程或系统设计模式,指的是发起一个操作后,不关心其执行结果或状态,也不等待其完成,直接继续后续流程。这种方式适用于非关键任务或允许最终一致性的场景,…

深入解析:wpf之命令

深入解析:wpf之命令pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "…

【技术术语】指数退避策略

【技术术语】指数退避策略指数退避策略 (Exponential Backoff) 指数退避是一种在网络通信和分布式系统中广泛使用的算法,用于协调重试失败的请求或操作。它的核心思想是:随着连续失败的次数增加,系统会逐渐延长重试…

【技术术语】冒烟测试

【技术术语】冒烟测试冒烟测试(Smoke Testing)是软件测试中的一种初步测试方法,用于快速验证系统的基本功能是否正常,确保软件的核心流程没有严重缺陷。它的名称来源于电路板测试中的“通电冒烟”比喻——如果基本…

2025年同步带直线滑台模组批发厂家权威推荐榜单:同步带直线滑块模组/伺服电机同步带直线模组/直线同步带模组源头厂家精选

在工业自动化高速发展的背景下,同步带直线滑台模组作为核心传动部件,其性能直接关系到自动化设备的定位精度与生产效率。据行业数据显示,2025年全球直线模组市场需求同比增长18.6%,其中同步带模组因速度快、行程长…

【技术术语】服务等级协议

【技术术语】服务等级协议SLA 在计算机和IT服务领域是 Service Level Agreement(服务等级协议) 的缩写,是服务提供商与客户之间定义服务质量和责任的法律协议。以下是关键要点:核心内容服务指标可用性:如服务器正…

【技术术语】命令查询职责分离

【技术术语】命令查询职责分离CQRS(命令查询职责分离)中文解析 CQRS(Command Query Responsibility Segregation)是一种架构模式,它将数据读取操作(查询)与数据更新操作(命令)分离。以下是详细说明: 核心概念…

2025年粉末分级机气流优质厂家权威推荐榜单:气流分级机/气流分级机供应/卧式气流分级机源头厂家精选

在粉体工业领域,气流分级机作为精细分级的关键设备,其技术水平直接影响着粉体产品的粒度分布和产品质量。根据行业数据显示,2024年中国粉体设备市场规模同比增长12.5%,其中气流分级机在非金属矿、新能源材料等领域…

【技术术语】蓝绿部署

【技术术语】蓝绿部署蓝绿部署(Blue-Green Deployment)详解 蓝绿部署是一种零停机时间的应用发布策略,通过维护两个完全相同的生产环境(蓝色和绿色)来实现无缝切换和快速回滚。 核心概念蓝色环境(Blue):当前正在运…

图的易错点

图的易错点处理多组图时 vector<pair<int,int>>e[N]需要在每次新建图时清空 /*错误操作: */ e.clear();/* 正确操作: */ for(int i=1;i<=n;i++){e[i].clear(); }

2025年汽车内饰模具批发厂家权威推荐榜单:汽车轻量化模具/复材模具定制/机器人模具源头厂家精选

在汽车产业转型升级与轻量化趋势加速的背景下,汽车内饰模具市场正迎来快速增长。据行业数据显示,2024年全球汽车内覆盖件模具市场规模达到5.11亿美元,预计到2031年将增长至6.75亿美元,期间年复合增长率约为4.1%。中…