[2016北京集训测试赛(十)]azelso-[概率/期望dp]

Description

Solution

感谢大佬的博客https://www.cnblogs.com/ywwyww/p/8511141.html

定义dp[i]为[p[i],p[i+1])的期望经过次数,f[i]为处理完事件i后不会再回到i点或以前,直接到终点的概率。

则$dp[i]=1+(1-f[i])+(1-f[i])^{2}+......=\frac{1}{f[i]}$

设事件i+1的胜率为k。

1:下一个事件是敌人,则f[i]=kf[i+1],即$dp[i]=\frac{dp[i+1]}{k}$。

2:下一个事件是旗子,则$f[i]=f[i+1](1+k(1-f[i+1])+k^{2}(1-f[i+1]^{2}+...)=\frac{f[i+1]}{1-k+kf[i+1]}$

把f替换为dp得$dp[i]=(1-k)dp[i+1]+k$

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int mod=1e9+7;
typedef long long ll;
ll ksm(ll x,ll k)
{
    ll re=1;
    while (k)
    {
        if (k&1) re=re*x%mod;
        k>>=1;
        x=x*x%mod;
    }
    return re;
}
ll h,n;
ll p[100010],a[100010],b[100010];char c[100010][2];
ll dp[100010],ans=0;
int main()
{
    scanf("%lld%lld",&h,&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%s%lld%lld%lld",c[i],&p[i],&a[i],&b[i]);
        a[i]=a[i]*ksm(b[i],mod-2)%mod;
    }
    dp[n]=1;
    for (int i=n;i;i--) 
    if (c[i][0]=='X') dp[i-1]=dp[i]*ksm(a[i],mod-2)%mod;
    else dp[i-1]=((1-a[i]+mod)%mod*dp[i]%mod+a[i])%mod;
    p[n+1]=h;
    for (int i=0;i<=n;i++) ans=(ans+(p[i+1]-p[i])%mod*dp[i]%mod)%mod;
    cout<<ans;
}

猜你喜欢

转载自www.cnblogs.com/coco-night/p/9640686.html