Candy UVA 1639 (数学期望)

这篇博客介绍了ACM竞赛中的一道题目Candy UVA 1639,探讨了如何计算当两个盒子取糖概率分别为p和1-p时,直到一个盒子没糖,另一个盒子剩余糖的数学期望。通过期望公式和组合数学,解决了由于高精度可能导致的误差,并给出了利用对数优化计算的方法和相应的代码实现。

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

Candy UVA 1639 (数学期望)

有两个盒子各有n颗糖(n<=2*105),从两个盒子取糖的概率为p和1-p,直到一个盒子没糖,求另一个盒子中糖的个数的数学期望。

期望公式为:
E = ∑ i = 1 n i ∗ E ( i ) = ∑ j = 0 n ( n − j ) ∗ C n + j j [ p n + 1 ∗ ( 1 − p ) j + ( 1 − p ) n + 1 ∗ p j ] E=\sum_{i=1}^{n}i*E(i)=\sum_{j=0}^{n}(n-j)*C_{n+j}^{j}[p^{n+1}*(1-p)^{j}+(1-p)^{n+1}*p^{j}] E=i=1niE(i)=j=0n(nj)Cn+jj[pn+1(1p)j+(1p)n+1pj]

假设最终看到盒子1没糖,那么盒子1刚好被选中n+1次(包括最后一次被选到)。那么从盒子2拿出糖的个数设为j,所以此时另一个盒子的糖的个数为n-j。整个过程中作出选择的次数为n+j+1,由于最后一次选择必为盒子1,所以只能在前n+j次选择盒子2,选择了j次(拿走了j颗糖),所以有C(n+j,j)种情况。

同理于对于最终看到盒子2没糖的情况。

由于n最高可达2*105,组合数最高可达C(2n,n),而且p的n次幂会非常趋近于0,如果直接相乘会造成较大的精度损失。这种情况可以用对数处理。

C n + j j ∗ p n + 1 ∗ ( 1 − p ) j = e ln ⁡ ( C n + j j ∗ p n + 1 ∗ ( 1 − p ) j ) = e ln ⁡ C n + j j + ( n + 1 ) ∗ ln ⁡ p + j ∗ ln ⁡ ( 1 − p ) C_{n+j}^j*p^{n+1}*(1-p)^j =e^{\ln_{}{(C_{n+j}^j*p^{n+1}*(1-p)^j)}} =e^{\ln_{}{C_{n+j}^j}+(n+1)*\ln_{}{p}+j*\ln_{}{(1-p)}} Cn+jjpn+1(1p)j=eln(Cn+jjpn+1(1p)j)=elnCn+jj+(n+1)lnp+jln(1p)

C n + j + 1 j + 1 = C n + j j ∗ ( n + j + 1 ) j + 1 C_{n+j+1}^{j+1}=C_{n+j}^{j}*\frac{(n+j+1)}{j+1} Cn+j+1j+1=Cn+jjj+1(n+j+1)
ln ⁡ C n + j + 1 j + 1 = ln ⁡ C n + j j + ln ⁡ ( n + j + 1 ) − ln ⁡ ( j + 1 ) \ln_{}{C_{n+j+1}^{j+1}}=\ln{}{C_{n+j}^{j}}+\ln{(n+j+1)}-\ln{(j+1)} lnCn+j+1j+1=lnCn+jj+ln(n+j+1)ln(j+1)
可以先计算指数部分。
E ( n − j ) = ( n − j ) ∗ [ e ln ⁡ C n + j j + ( n + 1 ) ∗ ln ⁡ p + j ∗ ln ⁡ ( 1 − p ) + e ln ⁡ C n + j j + ( n + 1 ) ∗ ln ⁡ ( 1 − p ) + j ∗ ln ⁡ p ] E(n-j)=(n-j)*[e^{\ln_{}{C_{n+j}^j}+(n+1)*\ln_{}{p}+j*\ln_{}{(1-p)}}+e^{\ln_{}{C_{n+j}^j}+(n+1)*\ln_{}{(1-p)}+j*\ln_{}{p}}] E(nj)=(nj)[elnCn+jj+(n+1)lnp+jln(1p)+elnCn+jj+(n+1)ln(1p)+jlnp]

代码如下:

#include<bits/stdc++.h>
using namespace std;
int main(void)
{
//	freopen("out.txt","w",stdout);
	int n;
	long double p;
	int t=1;
	while(cin>>n>>p)
	{
		long double lgp=log(p);
		long double lgp1=log(1-p);
		long double lgpn=(n+1)*lgp;
		long double lgp1n=(n+1)*lgp1;
		long double lgc=log(1);
		long double ans1=lgc+lgpn;
		long double ans2=lgc+lgp1n;
		long double ans=(long double)n*(exp(ans1)+exp(ans2));
		for(int j=1;j<n;j++)
		{
			lgc+=log(n+j)-log(j);
			ans1=lgc+lgpn+j*lgp1;
			ans2=lgc+lgp1n+j*lgp;
			ans+=(long double)(n-j)*(exp(ans1)+exp(ans2));
		}
		printf("Case %d: %.6Lf\n",t++,ans);
	}
//	fclose(stdout);
}
//10 0.400000
//100 0.500000
//124 0.432650
//325 0.325100
//532 0.487520
//2276 0.720000
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值