日常刷题2025-3-22

日常刷题2025-3-22

E - Expansion Packs

蓝色

https://atcoder.jp/contests/abc382/tasks/abc382_e

评述:期望DP+概率DP

一道非常棒的DP题目,非常推荐。典型的自以为做不了实际上思考上的困难在实现过程中都没遇到。

代码

#include<bits/stdc++.h>
using namespace std;
int n,X,p[5002];
double f[5002],g[5002],h[5002][5002],P[5002];
int main(){
	scanf("%d%d",&n,&X);
	for(int i=1;i<=n;++i)scanf("%d",&p[i]),P[i]=1.0*p[i]/100;
	//f[i] 表示一包卡恰好抽出 i 张 rare card(s) 的概率
	//h[i][j] 表示一包卡的前 i 张卡抽出 j 张 rare card(s) 的概率
	h[0][0]=1;
	for(int i=0;i<n;++i)
		for(int j=0;j<=n;++j){
			h[i+1][j]+=h[i][j]*(1-P[i+1]);
			h[i+1][j+1]+=h[i][j]*P[i+1];
		}
	for(int i=0;i<=n;++i)f[i]=h[n][i];
	//空间复杂度 O(n^2),因为需要 h,但可以优化到 n(类似滚动数组,但更简单) 
	//DP 类似背包。 
    //g[i]:抽出至少i张稀有卡期望抽g[i]包。
	//g[0]=0
	for(int i=1;i<=X;++i){
		double sum=0,alpha=0;
		for(int j=0;j<=n;++j){
			if(j>=i)continue;
			if(j==0)alpha=f[j];
			else sum+=f[j]*g[i-j];
		}
		sum+=1;
		g[i]=sum/(1-alpha); 
	}
	printf("%.10lf",g[X]);
}



posted @ 2025-03-22 10:33  califeee  阅读(4)  评论(0)    收藏  举报