ABC243F

发现直接记录有哪些奖品被选是不可能的,所以考虑转换一下思路:设 dpi,j,p 为只考虑前 i 个奖品,抽了 j 次,有 p 种不同奖品的的概率。

这个状态相当于是维护一个操作(抽奖)序列。考虑每次加入 q 个第 i 种奖品,就相当于是将原序列和一个由 qi 组成的序列合并。这是经典问题,方案数即为 (jq)。而该序列出现概率又为 dpi1,jq,p1×(wiw)q。还需要判断一下一些 0/1 的情况。

code:

点击查看代码
int n,m,k,e[N],f[N],dp[N][N][N];
inline int qpow(int x,int y){
	int ret=1;
	while(y){
		if(y&1)
			ret=1ll*ret*x%mod;
		x=1ll*x*x%mod;
		y>>=1;
	}
	return ret;
}
inline int Cnm(int x,int y){
	if(x<0||y<0||x<y)
		return 0;
	return 1ll*f[x]*qpow(1ll*f[y]*f[x-y]%mod,mod-2)%mod;
}
void solve(){
	scanf("%d%d%d",&n,&m,&k);
	int sm=0;
	f[0]=1;
	for(int i=1;i<=k;i++)
		f[i]=1ll*f[i-1]*i%mod;
	for(int i=1;i<=n;i++){
		scanf("%d",&e[i]);
		sm+=e[i];
	}
	dp[0][0][0]=1;
	for(int i=1;i<=n;i++){
		dp[i][0][0]=dp[i-1][0][0];
		for(int j=1;j<=k;j++){
			for(int p=1;p<=min(i,m);p++){
				dp[i][j][p]=dp[i-1][j][p];
				for(int q=1;q<=j;q++){
					dp[i][j][p]=(dp[i][j][p]+1ll*dp[i-1][j-q][p-1]*Cnm(j,q)%mod*qpow(e[i],q)%mod*qpow(qpow(sm,q),mod-2)%mod)%mod;
				}
			}
		}
	}
	printf("%d\n",dp[n][k][m]);
}
signed main(){
	int t=1;
	//	scanf("%d",&t);
	while(t--)
		solve();
}
posted @   yinhee  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示