题意:有 k 只 Tribles , 每一只 Trible 可以恰好活一天,第二天会死,死的时候生下一些小 Tribles, 每只小 Trible 继续活和生仔。现在要知道第 m 天时没有 Trible 的概率是多少。已知每一只 Trible 产下的小 Trible 的数量为 [0,n-1], 概率分别为 $P_0,P_1,*,P_{n-1}$,也就是产下 i 只的概率为 $P_i$(m,n,k∈[0,1000], 有多组数据)

思路:很自然地想到用 f[i][j] 表示第 i 天有 j 只 Trible 地概率,递推即可。问题是对于每个状态我们又要花 O(m) 转移,所以绝对行不通。

那么如果直接用 f[i] 表示第 i 天没有 Trible 的概率呢?其实可以。首先明确一个事实:我们只需要知道对于 1 只 Trible 的 f[i],答案最后取 k 次幂即可。现在如果要求第 i 天没有 Trible 的概率,那么首先你得让第一只 Trible 生的孩子死光,那么就是 $f[i-1]^x$, 其中 x 为生的数量 (每一只都得死,所以是 x 只的概率乘起来)。所以得出一个优美的公式

\begin{equation}
f[i]=\sum_{i=0}^{n-1}{P_i*f[i-1]^i}
\end{equation}

这样就可以在 O(nm) 的复杂度内求解啦!

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>

#define MX 1005

using namespace std;

int n,k,m;
double p[MX],f[MX];

void input()
{
    scanf("%d%d%d",&n,&k,&m);
    for(int i=0;i<=n-1;i++)scanf("%lf",&p[i]);
}

int main()
{
    int t;
    scanf("%d",&t);
    for(int w=1;w<=t;w++)
    {
        input();
        memset(f,0,sizeof(f));
        for(int i=1;i<=m;i++)
            for(int j=0;j<=n-1;j++)
                f[i]+=pow((double)f[i-1],j)*p[j];
        printf("Case #%d: %.7f\n",w,pow(f[m],k));
    }
    return 0;
}
分类: 文章

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注