Hdu 4465 Candy (快速排列组合+概率)

题目链接:

  Hdu 4465 Candy

题目描述:

  有两个箱子,每个箱子有n颗糖果,抽中第一个箱子的概率为p,抽中另一个箱子的概率为1-p。每次选择一个箱子,有糖果就拿走一颗,没有就换另外一个箱子。问换箱子的时候,另外一个箱子中剩下糖果的期望值。

解题思路:

  注意题目描述,其中任意一个箱子没有糖果,另一个箱子中剩下糖果个数的期望,而不是第一个箱子没有糖果。不是把其中一个箱子取空时,另一个箱子剩下糖果的期望,而是其中一个箱子取空再换另外一个箱子时,这个箱子的期望。

  可以根据期望性质画出公式:ans = (n-i) * C(n+i,n) * (p^(n+1)*(1-p)^i + (1-p)^(n+1)*p^i) (0<=i<=n);新的问题又来了,C(n+i,n)由于n的原因可能会向上溢出,而p^(n+1)又可能会很小,然后向下溢出。可以分别对他们进行取log,log(C(n+i,n))范围变小,log(p^(n+1))变成负数,方便保存。

 1 /*
 2 ******未处理精度的代码,推论严密美丽也无卵用********
 3 期望公式Ε=∑ P * N    p为概率 n为数量
 4  P=p*C(n,m)*p^n*(1-p)^(m-n)
 5  c(m,n)=c(m-1,n)*m/(m-n)
 6 概率
 7 m=0      p^(n+1)
 8 m=1      p^(n+1)q
 9 m=2      p^(n+1)q^2
10 */
11 #include <cstdio>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15
16 int main ()
17 {
18     int t, i, l = 1;
19     double ans, p1, p2, res1, res2;
20     while (scanf ("%d %lf", &t, &p1) != EOF)
21     {
22         p2 = (1.0 - p1);
23         res1 = t * p1;
24         ans = 1;
25         res2 = t * p2;
26         for (int i=1; i<=t; i++)
27         {
28             ans *= p1 * p2 * (t + i) / i;
29             res1 += ans * (t - i);
30             res1 *= p1;
31             res2 += ans * (t - i);
32             res2 *= p2;
33         }
34         printf ("Case %d: %6lf\n", l++, res1+res2);
35     }
36     return 0;
37 }
 1 /*
 2     取log处理精度问题,exp还原结果
 3 */
 4 #include <cmath>
 5 #include <cstdio>
 6 #include <iostream>
 7 #include <algorithm>
 8 using namespace std;
 9 const int maxn = 400005;
10 double Logf[maxn];
11 void init ()
12 {
13     Logf[0] = 0;
14     for (int i=1; i<maxn; i++)
15         Logf[i] = Logf[i-1] + log(i*1.0);
16 }
17 double C (int m, int n)
18 {
19     return Logf[m] - Logf[n] - Logf[m-n];
20 }
21 int main ()
22 {
23     int n, cas = 1;
24     double p1, p2, ans;
25     init ();
26     while (scanf ("%d %lf", &n, &p1) != EOF)
27     {
28         ans = 0;
29         p2 = 1.0 - p1;
30         p1 = log(p1);
31         p2 = log(p2);
32         for (int i=0; i<n; i++)
33         {
34             ans += ((n-i) * exp(C(n+i, n) + (n+1)*p1 + i*p2));
35             ans += ((n-i) * exp(C(n+i, n) + (n+1)*p2 + i*p1));
36         }
37         printf ("Case %d: %f\n", cas++, ans);
38     }
39     return 0;
40 }
时间: 2024-10-19 18:33:33

Hdu 4465 Candy (快速排列组合+概率)的相关文章

hdu 4465 Candy (快速排列组合 )

Candy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2115    Accepted Submission(s): 910 Special Judge Problem Description LazyChild is a lazy child who likes candy very much. Despite being ve

hdu 4465 Candy 2012 成都现场赛

1 /** 2 对于大数的很好的应用,,缩小放大,,保持精度 3 **/ 4 #include <iostream> 5 #include <cmath> 6 #include <algorithm> 7 #include <cstdio> 8 using namespace std; 9 10 int main() 11 { 12 double n,p; 13 int cnt =1; 14 while(cin>>n>>p){ 15

HDU 4465 Candy(组合+log优化)

题目大意:给你两个罐子,里面有糖果每次只能从一个罐子里面取一个糖果,打开A的概率为p,问当一个罐子取完之后,另一个罐子剩糖果的期望是多少. 我们可以知道最少是取第n+1次的时候才会有一个罐子为空,我们可以推出组合公式: (n-k)*C(n+k, k)*((1-p)^(n+1)*p^k+(1-p)^k*p^(n+k)):0 <= k && k <= n-1. 求一个和就是所有的组合情况了,但是组合数很大我们可以用log来进行优化. 我们已知:C(n,m) = m!/n!/(m-n

[概率+对数优化] hdu 4465 Candy

题意: 给两个盒子里面都有n个糖果,每次从第一个盒子里拿糖果的概率是p,另一个是1-p 问当拿完一个盒子时,另一个盒子还有多少糖果的期望. 其中有一点就是,当她打开盒子发现是空的时候 会去打开另一个盒子在同一天. 思路: 期望公式很好推: 但是推完就会出现各种溢出问题 所以要用对数优化 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath"

hdu 5698 瞬间移动(排列组合)

这题刚看完,想了想,没思路,就题解了 = = 但不得不说,找到这个题解真的很强大,链接:http://blog.csdn.net/qwb492859377/article/details/51478117 这个我只是看了他的思路,之后代码就自己写,之后交上去就是1A,我感觉好的题解就应该是这样的,Orz 要先看下他的思路,现在我在补充些我的理解: 首先,你要把行,列分开看,先说行,从1到n,1和n都不能走,因为1是开始,n是确定的,所以你有n-2种选择,你可以枚举x从1到n-2,就相当于高中学的

HDU 4465 Candy

Candy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2520    Accepted Submission(s): 1100Special Judge Problem DescriptionLazyChild is a lazy child who likes candy very much. Despite being very

hdu 2519 新生晚会 排列组合

通过阶段性计算减少一次性的大值计算 #include <stdio.h> int main() { int t, a, b, i; __int64 c; scanf("%d", &t); while(t--) { scanf("%d%d", &a, &b); if(a < b) printf("0\n"); else { c = 1; for(i = 1; i <= b; i++) c = c *

hdu 2519 新生晚会 排列组合基础

新生晚会 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 9203    Accepted Submission(s): 3230 Problem Description 开学了,杭电又迎来了好多新生.ACMer想为新生准备一个节目.来报名要表演节目的人很多,多达N个,但是只需要从这N个人中选M个就够了,一共有多少种选择方法? Inpu

HDU - 1261-字串数 (排列组合+大数)

一个A和两个B一共可以组成三种字符串:"ABB","BAB","BBA". 给定若干字母和它们相应的个数,计算一共可以组成多少个不同的字符串. Input每组测试数据分两行,第一行为n(1<=n<=26),表示不同字母的个数,第二行为n个数A1,A2,...,An(1<=Ai<=12),表示每种字母的个数.测试数据以n=0为结束. Output对于每一组测试数据,输出一个m,表示一共有多少种字符串. Sample Inpu