Candy
Total Submission(s): 1908 Accepted Submission(s): 833
Special Judge
He has been eating one candy a day for several days. But one day, when opening a box, he finds no candy left. Before opening the other box, he wants to know the expected number of candies left in the other box. Can you help him?
For each test case, there is a single line containing an integer n (1 ≤ n ≤ 2 × 105) and a real number p (0 ≤ p ≤ 1, with 6 digits after the decimal).
Input is terminated by EOF.
Any answer with an absolute error less than or equal to 10-4 would be accepted.
10 0.400000 100 0.500000 124 0.432650 325 0.325100 532 0.487520 2276 0.720000
Case 1: 3.528175 Case 2: 10.326044 Case 3: 28.861945 Case 4: 167.965476 Case 5: 32.601816 Case 6: 1390.500000
题目链接 :http://acm.hdu.edu.cn/showproblem.php?pid=4465
题目大意 :两个盒子开始都有n块糖,每次从一个中拿糖的概率为p,求当一个盒子空时,另一个盒子中糖的数目期望
题目分析 :不难得到公式: ans = 求和(i = 0~n)(n-i) * C(i, n + i) * ( (p ^ n* (1 - p) ^ i) + (p ^ i + (1 - p) ^ n)),本题n上限为20000,组合数存不下故中间过程要用递推公式即an = an * n / (n + 1) *(n + i) / i * p这样还是会卡精度有点坑爹,可以采用一个很简单的技巧。见程序
#include <cstdio>
#include <cmath>
int main()
{
int n, ca = 0;
double p;
while(scanf("%d %lf", &n, &p) != EOF)
{
double tmp1 = n, tmp2 = n ;
// printf("tmp1 = %f tmp2 = %f\n", tmp1, tmp2);
double ans1 = tmp1 * pow(1 - p, n + 1);
double ans2 = tmp2 * pow(p, n + 1);
int now = n;
int re = n + 1;
for(int i = 1; i < n; i++)
{
now = n - i; //系数
//递推公式
tmp1 *= 1.0 / (double)(now + 1) * p / i * (n + i) * now;
tmp2 *= 1.0 / (double)(now + 1) * (1 - p) / i * (n + i) * now;
//当tmp大于某个设定的值时让它乘p(或(1-p))来保证其数字不会暴精度
//关键技巧
while(tmp1 > n || tmp2 > n)
{
tmp1 *= (1 - p);
tmp2 *= p;
re--;
}
//因为每一项都要乘pow(1-p, n+1)或pow(p,n+1)
//我们在此补上剩余未乘的p(或(1-p))的幂数即可
ans1 += tmp1 * pow(1 - p, re);
ans2 += tmp2 * pow(p, re);
// printf("tmp1 = %lf tmp2 = %lf \n", tmp1, tmp2);
}
printf("Case %d: %lf\n", ++ca, ans1 + ans2);
}
}
837



被折叠的 条评论
为什么被折叠?



