CF 908 D New Year and Arbitrary Arrangement —— 期望DP

Posted zinn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF 908 D New Year and Arbitrary Arrangement —— 期望DP相关的知识,希望对你有一定的参考价值。

题目:http://codeforces.com/contest/908/problem/D

首先,设 f[i][j] 表示有 i 个 a,j 个 ab 组合的期望,A = pa / (pa + pb) , B = pb / (pa + pb)

那么 f[i][j] = A * f[i+1][j] + B * f[i][i+j]

当 i+j >= k 时,再出现一个 b 就会结束,所以此时:

f[i][j] = f[i][i+j] * B + f[i+1][i+j+1] * A * B + f[i+2][i+j+2] * A2 * B + ... + f[i+∞][i+j+∞] * A * B

化简一番(等比数列求和,1 - A = B)得到 f[i][j] = i + j + A / B

于是就可以做了;

不会刷表就记忆化搜索...

注意取的答案是 dp(1,0) 而非 dp(0,0),因为 dp(0,0) 会一直调用自己,而 dp(1,0) 可以看做是从第一个 a 出现开始算,反正前面没有 a ,对答案无影响。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=1005,mod=1e9+7;
int k,a,b,c,f[maxn*2][2*maxn];
bool vis[maxn][maxn];
int pw(int a,int b)
{
    int ret=1;
    for(;b;b>>=1,a=((ll)a*a)%mod)
        if(b&1)ret=((ll)ret*a)%mod;
    return ret;
}
int dp(int i,int j)
{
    if(vis[i][j])return f[i][j];
    vis[i][j]=1;
    if(i+j>=k)return f[i][j]=(i+j+c)%mod;
    f[i][j]=((ll)a*dp(i+1,j)+(ll)b*dp(i,i+j))%mod;
    return f[i][j];
}
int main()
{
    int pa,pb;
    scanf("%d%d%d",&k,&pa,&pb);
    int tmp=pw(pa+pb,mod-2); 
    a=(ll)pa*tmp%mod; b=(ll)pb*tmp%mod;
    c=(ll)a*pw(b,mod-2)%mod;
//    for(int i=0;i<=2*k;i++)
//        for(int j=max(k-i,0);j<=2*k;j++)
//            f[i][j]=f[j][i]=(i+j+c)%mod;
    // for(int i=k;i>=0;i--)
//        for(int j=k;j>=0;j--)
//            f[i][j]=(a*f[i+1][j]+b*f[i][i+j])%mod;
    printf("%d
",dp(1,0));//0,0 会调用自己
    //如果不是从第一个a算起,前面一堆b没用
    return 0;
}

 

以上是关于CF 908 D New Year and Arbitrary Arrangement —— 期望DP的主要内容,如果未能解决你的问题,请参考以下文章

[cf908G]New Year and Original Order

CF908D New Year and Arbitrary Arrangement 期望DP

Codeforces 908 D New Year and Arbitrary Arrangement

Codeforces 908 D.New Year and Arbitrary Arrangement (概率&期望DP)

CF908ENew Year and Entity Enumeration 位运算+DP

CF908DNew Year and Arbitrary Arrangement