专栏文章
P14364 [CSP-S 2025] 员工招聘 题解
P14364题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @min1rsjg
- 此快照首次捕获于
- 2025/12/01 19:09 3 个月前
- 此快照最后确认于
- 2025/12/01 19:09 3 个月前
设集合 ,考虑钦定一个集合 ,满足:
- 对于所有 ,第 个位置的人会被录取,即要求 ;
- 对于所有 ,第 个位置的人不会被录取,即要求 。
考虑容斥,把第一个条件的形式与第二个条件统一。具体地,钦定一个集合 ,满足:
- 对于所有 ,第 个位置的人不会被录取,即要求 ;
- 对于所有 ,第 个位置的人没有要求。
容斥系数为 。
考虑从前往后 dp。设 表示,考虑到第 个位置,此时一共有 个数在 中, 个数在 中,且仅考虑 中的位置填的数的方案数。初始化 ,设 ,,考虑转移:
- 若 ,;
- 若 :
- 令 ,;
- 令 ,;
- 令 ,。
其中,系数为 的原因是:当前位置填的数需要小于等于 ,且之前已经用了 个这样的数。
答案即为 ,其中 是满足 的 的数量,这些位置上的数可以任意排列。
使用滚动数组优化,空间复杂度 ,时间复杂度 。
Cconst int N=505,mod=998244353;
int n,m,c[N],s[N],a[N],b[N],f[2][N][N],fac[N],ans;
string str;
void add(int &a,int b){
a+=b;
if(a>=mod) a-=mod;
}
void solve(){
cin>>n>>m>>str;
for(int i=1;i<=n;i++) cin>>c[i],a[c[i]]++;
for(int i=1;i<=n;i++) s[i]=(str[i-1]=='1'),b[i]=b[i-1]+s[i];
for(int i=0;i<=n;i++) a[i]+=a[i-1];
f[0][0][0]=1,fac[0]=1;
for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod;
for(int i=0;i<n;i++){
int t=i&1;
memset(f[t^1],0,sizeof f[t^1]);
for(int j=0;j<=b[i];j++){
for(int k=0;k<=j;k++){
if(s[i+1]==0) add(f[t^1][j][k],f[t][j][k]);
else{
add(f[t^1][j+1][k],f[t][j][k]);
int x=a[i-j]-k-b[i]+j;
add(f[t^1][j][k],1ll*f[t][j][k]*x%mod);
add(f[t^1][j+1][k+1],1ll*f[t][j][k]*x%mod);
}
}
}
}
for(int j=m;j<=b[n];j++){
for(int k=0;k<=j;k++){
int x=n-b[n]+j-k;
if(k&1) add(ans,mod-1ll*f[n&1][j][k]*fac[x]%mod);
else add(ans,1ll*f[n&1][j][k]*fac[x]%mod);
}
}
cout<<ans<<endl;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...