1. 程式人生 > >【[HNOI2015]亞瑟王】

【[HNOI2015]亞瑟王】

i++ efi clas 題解 eof set har [1] 就是

神仙題,抄題解

\(tp_i\)表示\(i\)這個技能在\(r\)輪中被使用過的概率

於是最後的答案就是\(\sum_{i=1}^nd_i*tp_i\)

首先\(tp_1=1-(1-p_1)^r\),也就是連續\(r\)輪都沒有使用的概率

之後往下的\(tp\)\(dp\)來求

\(dp_{i,j}\)表示在一共\(r\)輪裏,前\(i\)個恰好有\(j\)個被發動的概率

那麽

\[tp_i=1-\sum_{j=0}^rdp_{i-1,j}*(1-p_i)^{r-j}\]

還是先算一下這個技能一直都沒有發動的概率,如果前面有\(j\)個技能使用了,那麽那對應的輪次是一定不會使用當前技能的,剩下的輪次,也就是\(r-j\)

輪我們讓其不發動就好了

之後是\(dp_{i,j}\)的轉移

如果這一個技能並沒有發動,那麽就從\(dp_{i-1,j}\)轉移過來

\[dp_{i,j}=dp_{i-1,j}*(1-p_i)^{r-j}\]

如果這個技能發動了,那麽就需要從前面的\(dp_{i-1,j-1}\)轉移

\[dp_{i,j}=dp_{i-1,j-1}*(1-(1-p_i)^{r-j+1})\]

我們還是先令技能\(i\)不發動,那麽前面就會有\(r-j+1\)個輪次可能發動,我們都讓其不發動,之後拿\(1\)減掉,就是發動的概率了

代碼

#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define maxn 225
#define min(a,b) ((a)<(b)?(a):(b))
double dp[maxn][maxn];
double p[maxn];
int d[maxn],n,T,m;
double tp[maxn];
inline double quick(double a,int b)
{
    double S=1.0;
    while(b) {if(b&1) S*=a;b>>=1,a*=a;}
    return S;
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        memset(dp,0,sizeof(dp));
        memset(p,0,sizeof(p));
        memset(tp,0,sizeof(tp)),
        memset(d,0,sizeof(d));
        scanf("%d%d",&n,&m);
        for(re int i=1;i<=n;i++)
            scanf("%lf%d",&p[i],&d[i]);
        dp[1][0]=quick((1-p[1]),m);
        dp[1][1]=1-dp[1][0];
        tp[1]=dp[1][1];
        for(re int i=2;i<=n;i++)
        {
            for(re int j=0;j<=min(i-1,m);j++)
                tp[i]+=dp[i-1][j]*quick((1-p[i]),m-j);
            tp[i]=1-tp[i];
            for(re int j=0;j<=min(i,m);j++)
            {
                dp[i][j]=dp[i-1][j]*quick((1-p[i]),m-j);
                if(j) dp[i][j]+=dp[i-1][j-1]*(1-quick((1-p[i]),m-j+1));
            }
        }
        double ans=0;
        for(re int i=1;i<=n;i++)
            ans+=tp[i]*d[i];
        printf("%.10lf",ans),putchar(10);
    }
    return 0;
}

【[HNOI2015]亞瑟王】