Codeforces908D. New Year and Arbitrary Arrangement【期望dp】

题目大意:

给定整数k,pa,pb。
初始有一个空序列,每次往末尾添加一个字符,有pa/(pa+pb)的概率添加a,有pb/(pa+pb)的概率添加b。
当ab作为子序列出现了至少k次的时候停止,问此时ab**子序列**出现次数的期望。对10^9+7取模。
1<=k<=1000,1<=pa,pb<=10^6。

解题思路:

f[i][j]表示当前有 i 个a,j 个ab子序列到停止时的期望,那么

f[i][j]=papa+pbf[i+1][j]+pbpa+pbf[i][j+i]

其实以上都不是重点,重点在于定下目标状态和终止状态值。

1.目标状态:
如果我们把目标状态定为f[0][0],那么

f[0][0]=(paf[1][0]+pbf[0][0])/(pa+pb)
会死循环,相当于一开始会有无穷多个b:bbbbb…….bbbbaababa…
但也可推出 f[0][0]=f[1][0],所以目标状态应为 f[1][0]

2.终止状态:
i+jk 时,再出现一个b就会停止,所以当 i+jk

f[i][j]=(i+j)B+(i+j+1)AB=(i+j+2)A2B+...
用差比数列的方法计算可得f[i][j]=i+j+papb

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}
const int N=1005,mod=1e9+7;
int k;ll pa,pb,inv_pb,f[N][N];
ll Pow(ll x,int y)
{
    ll res=1;
    for(;y;y>>=1,x=x*x%mod)
        if(y&1)res=res*x%mod;
    return res;
}
ll dfs(int i,int j)
{
    if(i+j>=k)return (i+j+pa*inv_pb)%mod;
    if(f[i][j]!=-1)return f[i][j];
    return f[i][j]=(dfs(i+1,j)*pa+dfs(i,j+i)*pb)%mod;
}
int main()
{
    //freopen("lx.in","r",stdin);
    memset(f,-1,sizeof(f));
    k=getint(),pa=getint(),pb=getint();
    pa=pa*Pow(pa+pb,mod-2)%mod,pb=(1-pa+mod)%mod,inv_pb=Pow(pb,mod-2);
    printf("%lld\n",dfs(1,0));
    return 0;
}
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cdsszjj/article/details/80342477
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

Codeforces908D. New Year and Arbitrary Arrangement【期望dp】

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭