毕业生的序列游戏

题目:
https://codeforces.ml/problemset/problem/908/D

有一个字符串,初始为空,每次随机添加 a a a b b b,当子序列为 a b ab ab的个数大于等于 k k k时停止。求最终得到的子序列 a b ab ab的个数的期望。

思路:
f ( i , j ) f(i,j) f(i,j)表示从字符串有 i i i a a a j j j a b ab ab时的状态,到最终态(即 a b ab ab的个数大于等于 k k k)的期望个数(期望 d p dp dp的套路,反着 d p dp dp),有 p a p_a pa概率添加a,同理 p b p_b pb p a + p b = 1 p_a+p_b=1 pa+pb=1则有
f ( i , j ) = p a ∗ f ( i + 1 , j ) + p b ∗ ( i , j + i ) f(i,j)=p_a*f(i+1,j)+p_b*(i,j+i)\\ f(i,j)=paf(i+1,j)+pb(i,j+i)
解释就是 i i i a a a j j j a b ab ab时的状态,添加 a a a就会到达 i + 1 i+1 i+1 a a a j j j a b ab ab时的状态,添加 b b b就会到达 i i i a a a i + j i+j i+j a b ab ab时的状态。答案就是 f ( 0 , 0 ) f(0,0) f(0,0)
现在考虑初始值

  • j ≥ k j\ge k jk
    f ( i , j ) = j f(i,j)=j f(i,j)=j
    因为已经结束了,得到的 a b ab ab一定是 j j j个。但这样还不够,比如 f ( 0 , 0 ) f(0,0) f(0,0) f ( 1 , 0 ) f(1,0) f(1,0)有关, f ( 1 , 0 ) f(1,0) f(1,0) f ( 2 , 0 ) f(2,0) f(2,0)有关,一直到 f ( ∞ , 0 ) f(\infty,0) f(,0)
  • i + j ≥ k , j < k i+j\ge k,j<k i+jk,j<k时,再添加 x ( 0 ≤ x ≤ ∞ ) x(0\le x\le \infty) x(0x)个连续的 a a a,然后在添加一个 b b b就能结束状态,最后得到 i + j + x i+j+x i+j+x a b ab ab,所以有
    f ( i , j ) = ∑ x = 0 ∞ p a x p b ( i + j + x ) = ( i + j ) p b ∑ x = 0 ∞ p a x + p b ∑ x = 0 ∞ x p a x ( p a ∞ = 0 ) = ( i + j ) p b 1 1 − p a + p b ∑ x = 0 ∞ x p a x \begin{aligned} f(i,j)&=\sum_{x=0}^{\infty}p_a^xp_b(i+j+x)\\ &=(i+j)p_b\sum_{x=0}^{\infty}p_a^x+p_b\sum_{x=0}^{\infty}xp_a^x\quad (p_a^{\infty}=0)\\ &=(i+j)p_b\frac{1}{1-pa}+p_b\sum_{x=0}^{\infty}xp_a^x\\ \end{aligned} f(i,j)=x=0paxpb(i+j+x)=(i+j)pbx=0pax+pbx=0xpax(pa=0)=(i+j)pb1pa1+pbx=0xpax
    ∑ x = 0 ∞ x p a x = 1 p a 1 + 2 p a 2 + 3 p a 3 + . . . + ∞ p a ∞ = ( p a 1 + p a 2 + p a 3 + . . . p a ∞ ) + ( p a 2 + p a 3 + . . . p a ∞ ) + ( p a 3 + . . . p a ∞ ) = ∑ i = 1 ∞ ∑ j = i ∞ p a j = p a ( 1 − p a ) 2 \begin{aligned} \sum_{x=0}^{\infty}xp_a^x&=1p_a^1+2p_a^2+3p_a^3+...+\infty p_a^{\infty}\\ &=(p_a^1+p_a^2+p_a^3+...p_a^{\infty})+(p_a^2+p_a^3+...p_a^{\infty})+(p_a^3+...p_a^{\infty})\\ &=\sum_{i=1}^{\infty}\sum_{j=i}^{\infty}p_a^j\\ &=\frac{p_a}{(1-p_a)^2} \end{aligned} x=0xpax=1pa1+2pa2+3pa3+...+pa=(pa1+pa2+pa3+...pa)+(pa2+pa3+...pa)+(pa3+...pa)=i=1j=ipaj=(1pa)2pa
    所以
    f ( i , j ) = i + j + p a p b f(i,j)=i+j+\frac{p_a}{p_b}\\ f(i,j)=i+j+pbpa
    所以要从 f ( 0 , 0 ) f(0,0) f(0,0)递归 d p dp dp计算,因为初始值有无穷多,没法从初始状态推。
#include<cstdio>
#include<cstring>
const int MAXK=1005,MOD=1000000007;

int pow_mod(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1)
            res=(1LL*res*a)%MOD;
        b>>=1;
        a=(1LL*a*a)%MOD;
    }
    return res;
}
int inv(int x)
{return pow_mod(x,MOD-2);}

int dp[MAXK][MAXK];
int k,pa,pb;

int DP(int i,int j)
{
    if(j>=k)
        return j;
    if(i+j>=k)
        return (i+j+1LL*pa*inv(pb)%MOD)%MOD;
    if(dp[i][j]!=-1)
        return dp[i][j];
    return dp[i][j]=(1LL*((1LL*pa*DP(i+1,j))%MOD+(1LL*pb*DP(i,i+j))%MOD)*inv(pa+pb))%MOD;
}

int main()
{
    scanf("%d%d%d",&k,&pa,&pb);
    memset(dp,-1,sizeof dp);
    printf("%d\n",DP(1,0));
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值