搜集卡片 状态压缩+数学期望

本文探讨了一个经典的概率问题——搜集卡片所需的平均数量。通过状态压缩和递推的方式,给出了求解搜集N种不同卡片所需购买零食袋数的数学期望的具体算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NKOJ 2127 搜集卡片

问题描述

童年时代,你是否热衷于搜集零食里的卡片呢?比如你集齐了108张水浒英雄的卡片,你会感到非常有成就感,而且还可以去兑换奖品。

作为一个聪明的小孩,你注意到如果你要赢得奖品,你必须买很多很多的零食才能搜集齐卡片。要赢得奖品,你估计要买多少袋零食才能成功?

输入格式

第一行,一个整数N(1 <= N <= 20), 表示总共有N种不同的卡片。
第二行,N个空格间隔的实数p1, p2, …, pN, (p1 + p2 + … + pN <= 1), 表示零食袋中每种卡片出现的概率。
注意:一包零食中最多有一张卡片,也可能一张都没有。

输出格式

一个实数,表示你计算的结果,保留6位小数

样例输入

2
0.1 0.4

样例输出

10.500000


数学期望水题,权当是复习。

显然应该用递推的方式解决此问题,为了递推我们需要记录状态,这道题记录状态显然用状态压缩。

f[x]表示在x的二进制表示的状态下,要全部搜集完需要买零食的期望值。那么有初值f[(1<<N)1]=0

接下来考虑递推式:

f[x]=pf[x]+pf[x]+ipif[x|(1<<i1)]+1

由于有1pp=p,移项后整理得:
f[x]=(ipif[x|(1<<i1)]+1)÷p

代码:

#include<stdio.h>

int N,En;
double f[1048576+233],p[25];

int main()
{
    int i,j;
    double P,sum;

    scanf("%d",&N);
    for(i=1;i<=N;i++)scanf("%lf",&p[i]);

    En=(1<<N)-1;
    for(i=En-1;i>=0;i--)
    {
        sum=P=0;
        for(j=1;j<=N;j++)if(!(i&(1<<j-1)))sum+=p[j]*f[i|(1<<j-1)],P+=p[j];
        f[i]=(sum+1)/P;
    }

    printf("%.6lf",f[0]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值