hdu 4465 Candy 组合数(快速排列组合)

本文解析了一道关于两个装有相同数量糖果的箱子的概率问题,通过数学公式推导,使用快速排列组合方法求解期望值,并给出了C++实现代码。

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

题意:有两个箱子,每个箱子有n颗糖,选择第一个箱子的概率是p,另一个是q。每次随机选择一个箱子并取一颗糖,若无糖可取,则换箱子。问换箱子的时候,另一个箱子的剩余糖数量的期望。

题解:先正确理解,不是一个箱子没有糖的时候的期望,而是一个箱子没有糖后再次被选择的时候的期望。所以可以得出公式为ans=∑(C(i-1,n)*p^(n+1)*q^(i-n-1)+C(i-1,n)*q^(n+1)*p^(i-n-1))*(2*n-m+1)(n<i<=2*n)。由于p^(n+1)可能很小,溢出double。所以要处理;还有C(i-1,n)的求解。我的方法是C(i,n)=C(i-1,n)+C(i-1,n-1)=i/(i-n)*C(i-1,n)。这样就可以递推求组合数了;再处理p^(n+1):可用x=(x+a)*p,a=a*p。的方法省去了较小的小数部分。由于double的大量运算,所以只能用G++交(15MS),用C++交就TLE了,相差真大啊。。

正解是用快速排列组合来解C(m,n)=exp(logC(m,n)),就是求log。整个公式都log一下,最后exp就简单多了,没想到啊,竟然被我蒙出来了。。



耗时:G++(15MS/1000MS),C++(TLE)。。。委屈

题解代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include <iostream>
using namespace std;
#define LL long long
int main()
{
    int n,tt=0;
    double p;
    while(scanf("%d%lf",&n,&p)!=EOF)
    {
        int i,j,k;
        double ans=0,x,y,num,q,a,b,pp,qq;
        q=1-p;
        a=1;
        b=1;
        x=y=0;
        for(i=n+1;i<=2*n;i++)
        {
            x=(x+a*(2*n-i+1))*p;
            y=(y+b*(2*n-i+1))*q;
            a=a*q*i/(i-n)*p;
            b=b*p*i/(i-n)*q;
        }
        ans=x*p+y*q;
        printf("Case %d: %.6lf\n",++tt,ans);
    }
    return 0;
}



快速排列组合函数(别人那弄来的。。就是求log):

f[0]=0;
for(int i=1;i<=400002;i++) f[i]=f[i-1]+log(i*1.0);
double logC(int m,int n){
    return f[m]-f[n]-f[m-n];
}
//C(m,n)=exp(logC(m,n))


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值