P14364 [CSP-S 2025] 员工招聘 题解
Coffee_zzz · · 题解
设集合
- 对于所有
i\in S ,第i 个位置的人会被录取,即要求c_i \gt \sum\limits_{j=1}^{i-1} [j \notin S] ; - 对于所有
i\in U\setminus S ,第i 个位置的人不会被录取,即要求c_i \le \sum\limits_{j=1}^{i-1} [j \notin S] 。
考虑容斥,把第一个条件的形式与第二个条件统一。具体地,钦定一个集合
- 对于所有
i \in T ,第i 个位置的人不会被录取,即要求c_i \le \sum\limits_{j=1}^{i-1} [j \notin S] ; - 对于所有
i \in S\setminus T ,第i 个位置的人没有要求。
容斥系数为
考虑从前往后 dp。设
- 若
s_{i+1}=0 ,f_{i+1,j,k} \leftarrow f_{i,j,k} ; - 若
s_{i+1}=1 :- 令
i+1 \in U\setminus S ,f_{i+1,j,k} \leftarrow f_{i+1,j,k}+f_{i,j,k} \times (a_{i-j}-k-b_i+j) ; - 令
i+1 \in S\setminus T ,f_{i+1,j+1,k} \leftarrow f_{i+1,j+1,k}+f_{i,j,k} ; - 令
i+1 \in T ,f_{i+1,j+1,k+1} \leftarrow f_{i+1,j+1,k+1}+f_{i,j,k} \times (a_{i-j}-k-b_i+j) 。
- 令
其中,系数为
答案即为
使用滚动数组优化,空间复杂度
const 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;
}