bzoj4008: [HNOI2015]亚瑟王

题目链接

bzoj4008: [HNOI2015]亚瑟王

题解

算出每张牌在r轮中打出的概率乘上权值
i在r轮中出现的概率$1 - (1 - p[i]) ^ r $
保证i本次为第一次打出概率,前面打了j张 概率$1 - (1 - p[i])^{r - j} $
\(dp[i][j]\) 表示,前i张牌,打出了j张的概率
转移分打不打i讨论一下
那么打i牌的概率为$\sum_j^{i ,r} dp[i - 1][j] * (1 - (1 - p[i])^{r - j}) $

题解

#include<bits/stdc++.h> 
using namespace std; 
int n,r; 
const int maxn = 555; 
double dp[maxn][maxn],p[maxn],g[maxn]; 
int d[maxn]; 
/*double pow(double x,int k) { 
    double ret = 1.0; 
    for(;k;k >>= 1,x *= x) if(k & 1) ret *= x; 
    return ret; 
} */
double pw[maxn][maxn]; 
int main() { 
    int Qwq; 
    scanf("%d",&Qwq);  
    while(Qwq -- ) { 
        memset(dp,0,sizeof dp); 
        memset(g,0,sizeof g); 
        scanf("%d%d",&n,&r); 
        for(int i = 1;i <= n;++ i) scanf("%lf%d",p + i,d + i),pw[i][0] = 1.0; 
        for(int i = 1;i <= n;++ i) for(int j = 1;j <= r;++ j) 
            pw[i][j] = pw[i][j - 1] * (1.0 - p[i]); 
        dp[1][1] = g[1] = 1.0 - pw[1][r]; dp[1][0] = pw[1][r]; 
        for(int i = 2;i <= n;++ i) { 
            for(int j = 0;j <= std::min(i,r);++ j)  { 
                if(j) dp[i][j] += dp[i - 1][j - 1] * (1.0 - (pw[i][r - j + 1]));  
                if(i != j) dp[i][j] += dp[i - 1][j] * pw[i][r - j];   
                g[i] += dp[i - 1][j] * (1.0 - pw[i][r - j]); 
            } 
        } 
        double ans = 0; 
        for(int i = 1;i <= n;++ i)  ans += g[i] * d[i];  
        printf("%.10lf\n",ans); 
    } 
    return 0; 
} 

转载于:https://www.cnblogs.com/sssy/p/9297049.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值