【题解】HNOI-2015亚瑟王

Problem

bzoj_died

Solution

这题真心不会,Orz题解

大概讲一下吧:

考虑每一张牌用过后不可用了,所以考虑每一张牌在 r r 轮中使用的概率是比较可行的,最后所有牌的概率与伤害乘积和即为期望答案

那么设第x张牌使用的概率为 fp[x] f p [ x ] ,在 r r 轮中前i张牌中使用 j j 张的概率为f[i][j]

方程:

f[i][j]=f[i1][j]·(1p[i])rj+f[i1][j1]·(1(1p[i])rj+1) f [ i ] [ j ] = f [ i − 1 ] [ j ] · ( 1 − p [ i ] ) r − j + f [ i − 1 ] [ j − 1 ] · ( 1 − ( 1 − p [ i ] ) r − j + 1 )

前面一项是当前一项不选, f[i1][j] f [ i − 1 ] [ j ] 表示前 i1 i − 1 张中已经使用了 j j 张牌,所以当前的牌在接下来的rj轮中始终不选,概率为 (1p[i])rj ( 1 − p [ i ] ) r − j
后面的一项是当前一项选,由于选取了这一张,所以要考虑后面剩下的 rj+1 r − j + 1 轮还没考虑,所以转移概率为 1(1p[i])rj+1 1 − ( 1 − p [ i ] ) r − j + 1

对于 fp[] f p [ ]

fp[i]=j=0rf[i1][j]·(1(1p[i])rj) f p [ i ] = ∑ j = 0 r f [ i − 1 ] [ j ] · ( 1 − ( 1 − p [ i ] ) r − j )

这个式子大意是求在每一轮中出现的概率相加

最后统计答案:

ans=i=1nfp[i]·d[i] a n s = ∑ i = 1 n f p [ i ] · d [ i ]

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rg register
#define cl(x) memset(x,0,sizeof(x))
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)>0?(x):(-(x)))

template <typename _Tp> inline _Tp read(_Tp&x){
    rg char c11=getchar(),ob=0;x=0;
    while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
    while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}

const int N=400;
double a[N],p[N],fp[N],mi[N][N],f[N][N];
int n,r;

int main(){
    int T;read(T);while(T--){
        cl(f),cl(fp);
        read(n),read(r);
        for(rg int i=1;i<=n;++i)scanf("%lf%lf",&p[i],&a[i]);

        for(rg int i=1;i<=n;++i){
            mi[i][0]=1;
            for(rg int j=1;j<=r;++j)
                mi[i][j]=mi[i][j-1]*(1.0-p[i]);
        }

        f[1][0]=mi[1][r];
        f[1][1]=fp[1]=1-f[1][0];
        for(rg int i=2;i<=n;++i)
            for(rg int j=0;j<=min(r,i);++j){
                fp[i]+=f[i-1][j]*(1-mi[i][r-j]);
                f[i][j]+=f[i-1][j]*mi[i][r-j];
                if(j)f[i][j]+=f[i-1][j-1]*(1-mi[i][r-j+1]);
            }
        double ans=0.0;
        for(rg int i=1;i<=n;++i)ans+=a[i]*fp[i];
        printf("%.10lf\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值