HDU 4465 递推与double的精确性
阅读原文时间:2023年07月16日阅读:1

题目大意不多说了

这里用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在计算过程中在答案超过总数时一个一个往里乘

#include
#include
#include
using namespace std;
const int N = ;
double dp[N][];

int main()
{
// freopen("test.in","rb",stdin);

 int n,cas = ;  
 double p;  
 while(scanf("%d%lf",&n,&p)!=EOF){  
     double ans1 = ;  
     double ans2 = ;  
     int last\[\];  
     last\[\] = last\[\] = n+;  
     double q = -p;  
     dp\[n\]\[\] = ;  
     dp\[n\]\[\] = ;  
     ans1 += n;  
     ans2 += n;  
     for(int i=n-;i>=;i--){  
         double tmp1 =  q \* (\*n-i) / (n-i);  
         double tmp2 =  p \* (\*n-i) / (n-i);

         //递推过程,因为数目太多,p直接开方,数据大点的话就直接因精确度不够变为0  
         //所以每次在答案超过总数的情况下乘个p值  
         dp\[i\]\[\] = tmp1 \* dp\[i+\]\[\];  
         dp\[i\]\[\] = tmp2 \* dp\[i+\]\[\];  
         ans1 += (dp\[i\]\[\] \* i);  
         while(ans1>n){  
             dp\[i\]\[\] \*= p;  
             ans1 \*= p;  
             last\[\]--;  
         }  
         ans2 += (dp\[i\]\[\] \* i);  
         while(ans2>n){  
             dp\[i\]\[\]\*=q;  
             ans2 \*= q;  
             last\[\]--;  
         }  
     }  
    // cout<<"  dp "<<dp\[n\]<<endl;  
     ans1 \*= pow(p,last\[\]);  
     ans2 \*= pow(q,last\[\]);  
     cas++;

     printf("Case %d: %.6f\\n",cas,ans1+ans2);  
 }  
 return ;  

}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章