At382 E - Expansion Packs

E.Expansion Packs


原题链接

题意简述

有无限个独立的牌组,每个牌组有n张卡组成,每张卡是稀有卡的概率位 \(p_i\) ,求抽到稀有卡的数量不小于x的需要抽的卡组数量的期望.

解题思路

显然每个牌组拥有稀有牌的数量也是一个不确定的,可以用一个数组存储当前牌组有 \(i\) 张稀有牌的概率是多少,转移方程为 \(f[i][j]=f[i-1][j-1]·p[i]+f[i-1][j]·1-p[i]\),所求出的\(f[n][i]\)就是每个牌组有 \(i\) 张牌的概率,确定这个之后思考牌组概率与最终需要期望的关系。注意到,期望可以通过概率进行逐步转移,考虑动态规划。定义 \(ans[i]\) 为抽到稀有卡数量不小于x至少需要抽到卡组数量的期望,那么就可以得到转移方程 \(ans[i]=\sum_{j=0} ^n ans[max(i-j,0)]·f[j]+1\),由于 \(ans[i]\) 能从 \(ans[i]·f[0]\) 转移过来,所以需要移项,除到右边 \(ans[i]=ans[i]·f[0]+\sum_{j=1} ^n ans[max(i-j,0)]·f[j]+1\),所以有\(ans[i]=(\sum_{j=1} ^n ans[max(i-j,0)]·f[j]+1)/(1-f[0])\)

AC code

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const ll inf=1e18;
int main(){
    cin.tie(0)->ios::sync_with_stdio(false);
    int n,m;
    cin>>n>>m;
    vector<long double>p(n+1);
    for(int i=1;i<=n;i++){
        int x;cin>>x;
        p[i]=1.0L*x/100;
    }
    vector<vector<long double> >f(n+1,vector<long double>(n+1));
    f[0][0]=1.0;
    for(int i=1;i<=n;i++){
        f[i][0]=f[i-1][0]*(1.0L-p[i]);
        for(int j=1;j<=n;j++){
            f[i][j]=f[i-1][j-1]*p[i]+f[i-1][j]*(1.0L-p[i]);
        }
    }
    vector<long double>ans(m+1);
    for(int i=1;i<=m;i++){
        ans[i]=1.0L;
        for(int j=1;j<=n;j++){
            ans[i]+=ans[max(i-j,0)]*f[n][j];
        }
        ans[i]/=(1.0L-f[n][0]);  
    }
    cout<<fixed<<setprecision(16)<<ans[m]<<endl;
    return 0;
}
posted @ 2025-05-26 22:45  usedchang  阅读(23)  评论(0)    收藏  举报