题解:重返现世
题意分析
kth Min-max 容斥
首先可以去除掉 \(p\) 中的 \(0\),因为 \(p_i=0\) 的 \(i\) 不会生成,对答案没有任何影响。
求收集到 \(k\) 种原料的期望时间,即求收集所有原料的期望时间的第 \(k\) 大时间。
那么就可以考虑 kth Min-max 容斥。
定义 \(\operatorname*{kthmin}\) 表示求第 \(k\) 小,\(\operatorname*{kthmax}\) 表示求第 \(k\) 大。
设 \(S=\set{1,2,3,\cdots,n}\),\(t_i=\dfrac{m}{p_i}\) 表示 \(i\) 被收集的期望时间。
集合 \(T\) 中的所有元素第一次被收集的期望时间为:
则题目所求即:
由 kth Min-max 容斥,则有:
\(\max t_i\) 实际上并不好求,所以为了利用 kth Min-max 容斥,我们可以将题目所求转化一下。
令 \(k'=n-k+1\),则题目所求为(以下 \(k'\) 适用于 \(\operatorname*{kthmax},\operatorname*{kthmin}\)):
注意到这道题目不像[PKUWC2018] 随机游走那般,可以直接枚举 \(T\),因此需要优化。
DP 求解
DP 状态
考虑 DP。因为 \(k'\leq11,m\leq10000,\sum\limits_{i=1}^np_i=m\),考虑与之有关的 DP。
设 \(\textit{dp}_{i,j,k}\) 表示考虑 \(S=\set{1,2,3,\cdots,i},\sum\limits_{l\in T}p_l=j\),\(\sum\limits_{T\subseteq S}(-1)^{\vert T\vert-k}\dbinom{\vert T\vert-1}{k-1}\) 的值(下文中 \(k\) 均不为题中 \(k\)),即:
DP 转移
-
如果 \(i\not\in T\),则有方案数为:
\[\textit{dp}_{i-1,j,k} \] -
否则 \(i\in T\),去除 \(i\) 的概率 \(p_i\),方案数即 \(\set{1,2,3,\cdots,i-1}\) 的方案数。
考虑组合数递推公式:
\[\dbinom{\vert T\vert-1}{k-1}=\dbinom{(\vert T\vert-1)-1}{k-1}+\dbinom{(\vert T\vert-1)-1}{(k-1)-1} \]那么,可以发现在 \(\dbinom{(\vert T\vert-1)-1}{(k-1)-1}\) 中 \(k\) 发生了 \(1\) 的变化,因此乘上 \(-1\)。
故,有方案数为:
\[\textit{dp}_{i-1,j-p_i,k-1}-\textit{dp}_{i-1,j-p_i,k} \]
故,有:
DP 边界
因为发现这样做是正确的,容斥函数中,\(T=\varnothing\) 是空集(因为概率和为 \(0\)),\((-1)^{0-0}=1\)。
但其实意义也不大,仅仅是为了保证后面有意义的地方计算正确而已。
答案统计
枚举概率和 \(i\),则有答案 \(\textit{ans}\) 为:
对于模意义下的 \(\dfrac1i\),使用乘法逆元即可。
滚动数组优化
这样的空间复杂度为 \(\mathcal O(nmk')\),会炸掉。
但是注意到 \(\textit{dp}_i\) 与 \(\textit{dp}_{i-2},\textit{dp}_{i-3},\cdots,\textit{dp}_0\) 均无关,因此可以使用滚动数组滚掉 \(i\) 这一维。
AC 代码
时间复杂度:\(\mathcal O(nmk')\)。
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
constexpr const int N=1000,M=10000,K=11,P=998244353;
int n,k,m,p[N+1],dp[2][M+1][K+1];
int qpow(int base,int n){
int ans=1;
while(n){
if(n&1){
ans=1ll*ans*base%P;
}
base=1ll*base*base%P;
n>>=1;
}
return ans;
}
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>k>>m;
k=n-k+1;
for(int i=1;i<=n;i++){
cin>>p[i];
if(!p[i]){
i--,n--;
}
}
dp[0][0][0]=dp[1][0][0]=1;
bool mode=0;
for(int i=1;i<=n;i++){
mode=!mode;
memset(dp[mode],0,sizeof(dp[mode]));
dp[mode][0][0]=1;
for(int j=1;j<p[i];j++){
for(int kk=1;kk<=k;kk++){
dp[mode][j][kk]=dp[!mode][j][kk];
}
}
for(int j=p[i];j<=m;j++){
for(int kk=1;kk<=k;kk++){
dp[mode][j][kk]=((1ll*dp[!mode][j][kk] + dp[!mode][j-p[i]][kk-1])%P - dp[!mode][j-p[i]][kk])%P;
}
}
}
int ans=0;
for(int i=1;i<=m;i++){
ans=(ans+1ll*dp[mode][i][k]*qpow(i,P-2)%P)%P;
}
ans=1ll*ans*m%P;
if(ans<0){
ans+=P;
}
cout<<ans<<'\n';
cout.flush();
/*fclose(stdin);
fclose(stdout);*/
return 0;
}

浙公网安备 33010602011771号