洛谷 P4707 重返现世

题面

题目描述

为了打开返回现世的大门,Yopilla 需要制作开启大门的钥匙。Yopilla 所在的迷失大陆有 \(n\) 种原料,只需要集齐任意 \(k\) 种,就可以开始制作。

Yopilla 来到了迷失大陆的核心地域。每个单位时间,这片地域就会随机生成一种原料。每种原料被生成的概率是不同的,第 \(i\) 种原料被生成的概率是 \(\frac{p_i}{m}\) 。如果 Yopilla 没有这种原料,那么就可以进行收集。

Yopilla 急于知道,他收集到任意 \(k\) 种原料的期望时间,答案对 \(998244353\) 取模。

输入输出格式

输入格式:

第一行三个数 \(n, k, m\)

第二行 \(n\) 个数 \(p_1, p_2, ..., p_n\)

输出格式:

输出一行。

输入输出样例

输入样例#1:

3 3 3

1 1 1

输出样例#1:

499122182

说明

对于 \(10 \%\) 的数据,\(p_1 = p_2 = ... = p_m\)

对于另外 \(10 \%\) 的数据,\(k = n\)

对于 \(70 \%\) 的数据,\(n \le 100\)

对于 \(100 \%\) 的数据,

\(1 \le n \le 1000\)\(1 \le k \le n, \lvert n - k \rvert \le 10\)

\(0 \le p_i \le m, \sum p = m, 1 \le m \le 10000\)

题目分析

%%%Trrui大佬

题目大意:求第\(k\)种原料的期望生成时间。

考虑广义min-max反演:

\[kth\_max(S)=\sum_{T\subseteq S}(-1)^{|T|-k}\binom{|T|-1}{k-1}min(T) \]

对于集合\(T\)

\[min(T)=\frac{m}{\sum_{i\in T}p_i} \]

我们设\(\text{dp}\)来求出\(\sum p_i\)相等的\(T\)的方案数。

\(f_{i,j}\)表示\(|T|=i,\sum_{i\in T}p_i=j\)时的方案数,转移十分显然。

时间复杂度为\(O(n^2m)\),可以得到\(70\)分的好成绩。


由于我们读入的\(k\)是第\(k\)小,而反演是用的是第\(k\)大,

所以,以下的\(k\)均为\(n-k+1\)

考虑改变\(\text{dp}\)状态,

\(f_{j,k}\)表示当\(\sum p_i=j\),\(k\)\((-1)^{|T|-k}\binom{|T|-1}{k-1}\)中的\(k\)时,\(\sum_{T}(-1)^{|T|-k}\binom{|T|-1}{k-1}\)的值。

对于一个\(p_i=v\)的新物品,考虑两种转移:

如果不加入,则\(f_{j,k}=f'_{j,k}\)

如果加入,我们需要用到一个trick:(Trrui大佬教我的)

由于\(k\)表示组合数,所以\(f_{j,k}\)\(f'_{j-v,k-1}\)相关。

\(g_{i,j}\)表示\(|T|=i,\sum_{i\in T}p_i=j\)时的方案数,则

\[f'_{j-v,k-1}=\sum_{i}(-1)^{i-k+1}\binom{i-1}{k-2}g_{i,j-v} \]

如果新增一个物品,则新的\(g_{i+1,j}=g_{i,j-v}\),对于转移前的\(g\)而言:

\[\Delta f_{j,k}=\sum_{i}(-1)^{i-k+1}\binom{i}{k-1}g_{i,j-v} \]

两式相减,

\[\begin{split} \Delta f_{j,k}-f'_{j-v,k-1}&=\sum_{i}(-1)^{i-k+1}\binom{i-1}{k-1}g_{i,j-v}\\ &=-\sum_{i}(-1)^{i+k}\binom{i-1}{k-1}g_{i,j-v}\\ &=-f'_{j-v,k} \end{split} \]

由此可得:

\[\begin{split} f_{j,k}&=f'_{j,k}+\Delta f_{j,k}\\ &=f'_{j,k}+f'_{j-v,k-1}-f'_{j-v,k} \end{split} \]

\(DP\)求解即可,时间复杂度\(O((n-k)\cdot m)\)

最终统计答案:

\[ans=\sum_{i=1}^m\frac{m}{i}f_{i,k} \]


考虑如何附初值:

对于初始情况而言:

\(f_{j,k}\)表示\(|T|=0,\sum p=j,组合数为k\)时的值,

由于没有\(i\),因此只有\(j=0\)有意义,我们只需处理\(f_{0,k}\)的初值。

根据广义二项式定理,

\[f_{0,k}=(-1)^{-k}\binom{-1}{k-1}=-1 \]

代码实现

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<iomanip>
#include<cstdlib>
#define MAXN 0x7fffffff
typedef long long LL;
const int N=1005,mod=998244353;
using namespace std;
inline int Getint(){register int x=0,f=1;register char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}return x*f;}
int ksm(int x,int k){
	int ret=1;
	while(k){
		if(k&1)ret=(LL)ret*x%mod;
		x=(LL)x*x%mod,k>>=1;
	}
	return ret;
}
int p[N],f[2][10005][15],ans;
int main(){
	int n=Getint(),K=n-Getint()+1,m=Getint();
	for(int i=1;i<=n;i++)p[i]=Getint();
	for(int i=1;i<=10;i++)f[0][0][i]=mod-1;
	int t=0;
	for(int i=1;i<=n;i++){
		t^=1,memset(f[t],0,sizeof(f[t]));
		for(int j=0;j<=m;j++){
			for(int k=1;k<=K;k++){
				f[t][j][k]=f[t^1][j][k];
				if(j>=p[i]){
					(f[t][j][k]+=mod-f[t^1][j-p[i]][k])%=mod;
					(f[t][j][k]+=f[t^1][j-p[i]][k-1])%=mod;
				}
			}
		}
	}
	for(int i=1;i<=m;i++)
		(ans+=(LL)m*ksm(i,mod-2)%mod*f[t][i][K]%mod)%=mod;
	cout<<ans;
	return 0;
}
posted @ 2019-03-08 16:41  Emiya_2020  阅读(290)  评论(0)    收藏  举报