• HDU 4465 递推与double的精确性


    题目大意不多说了

    这里用dp[i][0] 代表取完第一个盒子后第二个盒子剩 i 个的概率,对应期望就是dp[i][0] *i

    dp[i][1] 就代表取完第二个盒子后第一个盒子剩 i 个的概率

    dp[i][0]  =  p^(n+1) * (1-p)^(n-i) * C(2*n-i , n-i) = p^(n+1) * (1-p)^(n-i) * (2*n-i)! / (n-i)! / n!

    dp[i+1][0]  = p^(n+1) * (1-p)^(n-i-1) * C(2*n-i-1 , n-i-1) = p^(n+1) * (1-p)^(n-i-1) * (2*n-i-1)! / (n-i-1)! / n!

    dp[i][0] = dp[i+1][0] * (1-p) * (2*n-i) / (n-i)

    dp[i][1]也是一样的道理

    如果一开始给dp[n][0] 赋初值 pow(p,n+1) 那么如果n过大,那么因为精确度问题得到的是0

    所以n+1个p在计算过程中在答案超过总数时一个一个往里乘

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 using namespace std;
     5 const int N = 200005;
     6 double dp[N][2];
     7 
     8 int main()
     9 {
    10    // freopen("test.in","rb",stdin);
    11 
    12     int n,cas = 0;
    13     double p;
    14     while(scanf("%d%lf",&n,&p)!=EOF){
    15         double ans1 = 0;
    16         double ans2 = 0;
    17         int last[2];
    18         last[0] = last[1] = n+1;
    19         double q = 1-p;
    20         dp[n][0] = 1;
    21         dp[n][1] = 1;
    22         ans1 += n;
    23         ans2 += n;
    24         for(int i=n-1;i>=1;i--){
    25             double tmp1 =  q * (2*n-i) / (n-i);
    26             double tmp2 =  p * (2*n-i) / (n-i);
    27             
    28             //递推过程,因为数目太多,p直接开方,数据大点的话就直接因精确度不够变为0
    29             //所以每次在答案超过总数的情况下乘个p值
    30             dp[i][0] = tmp1 * dp[i+1][0];
    31             dp[i][1] = tmp2 * dp[i+1][1];
    32             ans1 += (dp[i][0] * i);
    33             while(ans1>n){
    34                 dp[i][0] *= p;
    35                 ans1 *= p;
    36                 last[0]--;
    37             }
    38             ans2 += (dp[i][1] * i);
    39             while(ans2>n){
    40                 dp[i][1]*=q;
    41                 ans2 *= q;
    42                 last[1]--;
    43             }
    44         }
    45        // cout<<"  dp "<<dp[n]<<endl;
    46         ans1 *= pow(p,last[0]);
    47         ans2 *= pow(q,last[1]);
    48         cas++;
    49 
    50         printf("Case %d: %.6f
    ",cas,ans1+ans2);
    51     }
    52     return 0;
    53 }
  • 相关阅读:
    用email实现邮件模板
    jquery.transform
    学习 表单验证插件validate
    倒计时
    时间
    听慕课学自定义滚动条
    css3动画、边框、投影知识
    sql查询字段值只为汉字(桃)
    sql按照汉字首字母顺序排序(桃)
    poi导出excel文件(桃)
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4034983.html
Copyright © 2020-2023  润新知