Light OJ 1038 - Race to 1 Again(概率DP)

题目的意思是说任何一个大于1的整数,经过若干次除以自己的因子之后可以变为1, 求该变换字数的数学期望值。

题目分析:

我们设置dp[n] 为数字n的期望。假设n的因子为k1, k2, k3.... 共有k个

那么 dp[n] = (dp[k1] + dp[k2] +..... + dp[n] + k)* (1/k)

公式化简一下:

dp[n] = (1/(k-1)) * (dp[k1] + dp[k2] .........+dp[n] + k)

式子出来记忆化搜索一下

===========================================================================================

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<map>
    using namespace std;
    typedef long long LL;
    const int INF = 1e9+7;
    const int MAXN = 100055;
    double dp[MAXN];

    double DFS(int n)
    {
        if(dp[n] != -1) return dp[n];

        dp[n] = 0;
        int len = sqrt(n+1), k = 0;
        for(int i=1; i<=len; i++)
        {
            if(i*i == n)
            {
                k ++;
                dp[n] += DFS(i);
            }
            else if(n%i == 0)
            {
                k += 2;
                dp[n] += DFS(i);
                dp[n] += DFS(n/i);
            }
        }
        dp[n] = 1.0/(k-1) * (dp[n] + k);
        return  dp[n];
    }

    int main()
    {
        int T, cas = 1, n;
        for(int i=0; i<= 100005; i++)
            dp[i] = -1;
        dp[1] = 0;
        scanf("%d", &T);
        while(T --)
        {
            scanf("%d", &n);

            printf("Case %d: %.6lf\n",cas ++, DFS(n) );
        }

        return 0;
    }
时间: 2024-10-25 08:10:45

Light OJ 1038 - Race to 1 Again(概率DP)的相关文章

Lightoj 1038 - Race to 1 Again (概率DP)

题目链接: Lightoj  1038 - Race to 1 Again 题目描述: 给出一个数D,每次可以选择数D的一个因子,用数D除上这个因子得到一个新的数D,为数D变为1的操作次数的期望为多少? 解题思路: 概率DP咯,对于只知道期望是:E(X) = X1*p(X1) + X2*p(X2) + …… + Xn*p(Xn)的窝,拿这个题目没有一点办法.然后看了讨论版,发现总会有一些神人存在. 求操作次数的期望时,先设定第i个因子给期望的贡献为Ti,那么有:E = (T1 + T2 + T3

[期望dp+记忆化搜索] light oj 1038 Race to 1 Again

题意: 给一个数n,每次随机选它的一个约数去除n,直到除到1为止,问除的次数的期望. 思路: E[n]= E[n/a[1]]/cnt+E[n/a[2]]/cnt+...+E[n/a[n]]/cnt+1 a[i]为n的约数,cnt为约数的个数. 显然a[i]=1  则(1-1/cnt)E[n]=E[n/a[2]]/cnt+...+E[n/a[n]]/cnt+1 记忆化搜索就ok了~ 代码: #include"cstdlib" #include"cstdio" #inc

light oj 1265 - Island of Survival(概率dp)

1265 - Island of Survival PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB You are in a reality show, and the show is way too real that they threw into an island. Only two kinds of animals are in the island, the tigers and t

Light OJ 1406 Assassin`s Creed 状态压缩DP+强连通缩点+最小路径覆盖

题目来源:Light OJ 1406 Assassin`s Creed 题意:有向图 派出最少的人经过全部的城市 而且每一个人不能走别人走过的地方 思路:最少的的人能够走全然图 明显是最小路径覆盖问题 这里可能有环 所以要缩点 可是看例子又发现 一个强连通分量可能要拆分 n最大才15 所以就状态压缩 将全图分成一个个子状态 每一个子状态缩点 求最小路径覆盖 这样就攻克了一个强连通分量拆分的问题 最后状态压缩DP求解最优值 #include <cstdio> #include <cstri

Light OJ 1027 - A Dangerous Maze(概率)

题目大意: 你在一个迷宫里,你面前有n个门,你选择门的概率是一样的,每扇门有一个数字k, 加入这个数字是负数,那么这个门会花费你abs(k)分钟后把你带回原点, 假如这个数字是正数,他可以把你带出迷宫,并且花费时间是k. 问把你带出迷宫的预计期望时间是多少?如果无解输出 “inf”,输出结果要求是最简分数的形式. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm>

Light OJ 1236 Race 第二类斯特林数

第二类斯特林数 n 匹马 分成1 2 3... n组 每一组就是相同排名 没有先后 然后组与组之间是有顺序的 在乘以组数的阶乘 #include <cstdio> #include <cstring> using namespace std; int dp[1010][1010]; int a[1010]; int main() { a[0] = 1; dp[0][0] = 1; for(int i = 1; i <= 1000; i++) { dp[i][0] = 0; d

LightOJ 1038 - Race to 1 Again 【DP】

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1038 题意:题目很短,不叙述了. 解法:dp 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #include <complex> #include <string> #include <functio

Light OJ 1032 - Fast Bit Calculations(数位DP)

题目大意: 一个数字把他看成二进制数字,数字里又会一些相邻的1,问从0到n至间所有相邻1的总和是多少? 分解成2进制数字,然后数位DP就行了. ======================================================================== #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<

Light OJ 1317 Throwing Balls into the Baskets 概率DP

?n个人 m个篮子 每一轮每一个人能够选m个篮子中一个扔球 扔中的概率都是p 求k轮后全部篮子里面球数量的期望值 依据全期望公式 进行一轮球数量的期望值为dp[1]*1+dp[2]*2+...+dp[n]*n 记为w 当中dp[i]为i个人扔中的概率 dp[i] = C(n, i)*p^i*(1-p)^(n-i) 终于答案为w*k #include <cstdio> #include <cstring> using namespace std; double dp[20]; dou