牛客多校训练第九场 E(思维+期望计算)

玩一场游戏,游戏中会有n个点,每个点被点击成功的概率是p[i],游戏结束后所得分数是每段点击成功的长度的m次方的总和,求所得分数的期望。n,m<=1000

例:0111011011(0代表这个店点击失败,1代表成功)

最后的得分是3^m+2^m+2^m.

枚举每个情况,然后计算得分成上相应概率,最后求出总和。情况有2^1000种,显然不行。

解题思路:

我们假设一场游戏的一个子情况是0111011011,那么这个对结果的贡献是(3^m+2^m+2^m)*P(这种情况发生的概率)

将此式拆开==> 3^m*P+2^m*P+2^m*P

我们考虑3^m*P这部分,等价于3^m*P1*P2(P1为前五个点为01110的概率,P2为后面为11011的概率),然后我们想一下,求最后的期望值,要算出所有的情况,那么其中就会有一些前五个点为01110的情况,那么这部分的和就为3^m*P1*(sum(p2,p3,p4......)),而sum(p2,p3,p4......)这部分等于1,因为后面的点将会发生所有情况,那么概率为1。而这只是算前五个点位01110的情况,我们还要算0110和11...和其他子情况的一段1,那么计算过程和上面是一样的,所以最后的结果就是将所有的连续1的序列的贡献求出来,累加一下就是答案。

代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define maxn 1005
const ll mod=1e9+7;
ll f[maxn][maxn];
ll p[maxn];
ll q[maxn];
ll qpow(ll a,ll k)
{
    ll res=1;
    while(k)
    {
        if(k&1)
        {
            res=res*a%mod;
        }
        k>>=1;
        a=a*a%mod;
    }
    return res;
}
int main()
{
    ll n,m;
    while(~scanf("%lld%lld",&n,&m))
    {
        ll inv=qpow(100,mod-2);
        memset(q,0,sizeof(q));
        for(int i=0;i<=n+1;i++)
        {
            q[i]=100*inv%mod;
        }
        for(int i=1; i<=n; i++)
        {
            scanf("%lld",&p[i]);
            q[i]=(100-p[i])*inv%mod;
            p[i]=p[i]*inv%mod;

        }
        for(int i=1; i<=n; i++)
        {
            f[i][i]=p[i];
            for(int j=i+1; j<=n; j++)
            {
                f[i][j]=f[i][j-1]*p[j]%mod;
            }
        }
        ll ans=0,temp;
        for(int i=1; i<=n; i++)
        {
            for(int j=i; j<=n; j++)
            {
                temp=f[i][j]*q[i-1]%mod*q[j+1]%mod*qpow(j-i+1,m);
                ans=(ans+temp)%mod;
            }
        }
        printf("%lld\n",ans);


    }
}

猜你喜欢

转载自blog.csdn.net/zyy_1998/article/details/81810302
今日推荐