Candy UVA - 1639(数学期望)

题目:

一个爱吃糖的小朋友获得了两盒糖果,每个盒子里均有n(n≤200000)个糖果,他每天随机选一个盒子(概率为 p1-p)吃掉里面的一个,直到有一天,打开盒子一看,没糖了!输入n,p求另一个盒子里剩余糖个数的数学期望。
VJ 题目链接

读完题我拿起计算器 (2e5/365=500+…)???

思路:

起初尝试解个方程,列出来带有组合数无法分离变量,只好放弃转向紫书
其思路大致为:按照另一个盒子剩余数量划分,总共n种情况,表达出第i种情况的概率,所求为 ∑(i<=n) 设最后打开的是1号盒,2号盒剩 i 个,则共打开n+1次1号盒,n-i次2号盒, P1 = C(2n-i, n) * p(n+1) * (1-p)(n-i) ;若最后打开的为2号盒交换 p 和 1-p 即可。但是直接计算组合数会溢出,所以要先取对数再取逆运算
需要注意的是,本题对精度要求很高,我是用的 long double ;非常有意思的是,如果声明p数据类型也为 long double 那么隐式转换的消耗会拖后程序40ms(可能有误差) 所以p仍保留double类型

具体实现:

(260ms 水码)

//#include "stdafx.h"
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <string>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <iomanip>
using namespace std;
typedef long double LD;
const int maxn = 4e5 + 1;
LD ln[maxn];

inline LD C(int m, int n) {
	return ln[m] - ln[n] - ln[m-n];
}

int main() {
	
	for (int i = 1; i < maxn; i++)//预处理组合数
		ln[i] = ln[i - 1] + log(i);
	int n, cp = 0;
	double p;
	while (cin >> n >> p) {
		LD E = 0.0;
		for (int i = 1; i <= n; i++) {

			LD c = C(2*n-i, n);
			LD k1 = log(p), k2 = log(1-p);
			LD v1 = c + (n + 1)*k1 + (n - i)*k2;//盒1空
			LD v2 = c + (n + 1)*k2 + (n - i)*k1;//盒2空
			E += i * (exp(v1) + exp(v2));
		}
		printf("Case %d: %.6Lf\n", ++cp, E);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值