专栏文章
ABC382-E 题解
AT_abc382_e题解参与者 7已保存评论 8
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 8 条
- 当前快照
- 1 份
- 快照标识符
- @miqx9swd
- 此快照首次捕获于
- 2025/12/04 12:14 3 个月前
- 此快照最后确认于
- 2025/12/04 12:14 3 个月前
题意
你有无数包卡牌,每包有 张,同时有 种稀有卡牌,每张稀有卡牌在每包中出现的概率为 ,问期望拆多少包卡牌可以获得 张稀有卡牌。
,。
思路
很显然,我们可以用 dp 解决这个问题。
设 为至少获得 张稀有卡牌的期望拆的包数, 为每包恰好获得 张卡牌的概率。
我们首先求解 ,我们可以考虑新加进来一种稀有卡牌,设新加进来第 种稀有卡,考虑转移 ,那么有两种情况,一种是前 种卡牌已经拆出 张的概率,另一种是前 种卡牌拆出 张,同时拆出来了第 种的概率,于是转移方程为 。类似于背包,要倒序转移。
再来求解 。转移时,我们可以枚举这一次拆出来的数量,借助 转移。要让总卡牌数至少为 ,如果这一包拆出 张,则原来至少有 张。方程即为 。
这样还有个问题, 会从自己转移过来,只需要把右边带 的项移到右边即可。
最终的式子即为 。
不理解可以结合代码食用。
Code
C#include <bits/stdc++.h>
#define endl '\n'
#define int long long
#define fi first
#define se second
using namespace std;
const int N=5000+10;
const int inf=0x3f3f3f3f3f3f3f3f;
double g[N];
double f[N];
int n,x;
double p[N],ans;
signed main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(false);
cin>>n>>x;
for(int i=1;i<=n;i++)
{
cin>>p[i];
p[i]/=100;
}
g[0]=1;
for(int i=1;i<=n;i++)
{
for(int j=n;j>=1;j--)
{
g[j]=g[j]*(1-p[i])+g[j-1]*p[i];
}
g[0]*=(1-p[i]);
}
for(int i=1;i<=x;i++)
{
f[i]=1;
for(int j=1;j<=n;j++)
{
f[i]+=f[max(0ll,i-j)]*g[j];
}
f[i]/=(1-g[0]);
}
printf("%.8lf",f[x]);
return 0;
}
相关推荐
评论
共 8 条评论,欢迎与作者交流。
正在加载评论...