日常刷题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]=0for(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]);
}