概率DP小结

本文分享了从概率动态规划入门到进阶的学习路线,包括独立事件期望的计算、不同类型的概率DP问题解决策略,并提供了LightOJ1038的代码示例。文章还推荐了几个练习题目,帮助读者巩固理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨天从金华回来,成绩不理想,但是也没办法,自己的问题,想知道比赛详情的请戳http://bbs.whu.edu.cn/wForum/disparticle.php?boardName=ACM_ICPC&ID=1105535232&pos=11

今年的比赛算是结束了,于是心想现在还是本着学习的态度,重新开始学习新的知识,于是想着就从DP开始吧。不知怎么地,搜到了一道概率DP的题目,就开始研究。

如果要学习概率DP,可以从LIGHT OJ的1027开始,再到POJ 2096,LIGHT OJ 1030,1038。差不多就有个入门级的了解了。


ACM比赛中,概率DP一般来说都是求数学期望。

对于独立事件之间的期望,可以注意到,如果每次求一次子概率,又碰到原来的那个情况,那么数学期望也是一样的,于是就可以列出一个最基本的一元一次方程,求解即可。LIGHT OJ 1027和LIGHT OJ 1038都是练习这种思维的好题。

对于其他类型的概率DP,我们可以试着从后面往前面推,什么意思呢?就是我们可以以dp[n]为起点,然后一直往前面推,找结论。具体的问题还得具体分析,LIGHT OJ 1030和POJ 2096都是这方面的好题。

当然,练习概率DP首先要对概率论的知识有所了解,否则肯定没法做题。


下面贴一个Light OJ 1038的代码,供参考:


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 111111;
double dp[maxn];

void calc_p()
{
    dp[2] = 2.0, dp[3] = 2.0;
    for(int i = 4; i <= 100000; i ++)
    {
        dp[i] = 0.0;
        for(int j = 2; j * j <= i; j ++)
        {
            if(i % j == 0)
                break;
            if((j + 1) * (j + 1) > i) // if i is a prime the its val is 2
                dp[i] = 2.0;
        }
    }
}

double calc_val(int n)
{
    double sm = 2.0;
    int cnt = 2;
    for(int i = 2; i * i <= n; i ++)
    {
        if(n % i == 0)
        {
            cnt ++;
            if(dp[i])
                sm += (1 + dp[i]);
            else
                sm += (1 + calc_val(i));
            if(i * i != n)
            {
                cnt ++;
                int j = n / i;
                if(dp[j])
                    sm += (1 + dp[j]);
                else
                    sm += (1 + calc_val(j));
            }
        }
    }
    dp[n] = sm / (cnt - 1);
    return dp[n];
}

int main()
{
    int cse, t = 1, n;
    calc_p();
    dp[1] = 0.0;
    scanf("%d", &cse);
    while(cse --)
    {
        scanf("%d", &n);
        printf("Case %d: ", t ++);
        if(n == 1)
        {
            printf("0.0000000000\n");
            continue;
        }
        if(dp[n])
            printf("%.10lf\n", dp[n]);
        else
            printf("%.10lf\n", calc_val(n));
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值