LIghtOJ1038---Race to 1 Again(概率dp)

Rimi learned a new thing about integers, which is - any positive integer greater than 1 can be divided by its divisors. So, he is now playing with this property. He selects a number N. And he calls this D.

In each turn he randomly chooses a divisor of D (1 to D). Then he divides D by the number to obtain new D. He repeats this procedure until D becomes 1. What is the expected number of moves required for N to become 1.

Input

Input starts with an integer T (≤ 10000), denoting the number of test cases.

Each case begins with an integer N (1 ≤ N ≤ 105).

Output

For each case of input you have to print the case number and the expected value. Errors less than 10-6 will be ignored.

Sample Input

Output for Sample Input

3

1

2

50

Case 1: 0

Case 2: 2.00

Case 3: 3.0333333333

Problem Setter: Jane Alam Jan

dp[i]表示把i变成1的期望次数

/*************************************************************************
    > File Name: c.cpp
    > Author: ALex
    > Mail: [email protected]
    > Created Time: 2015年04月29日 星期三 19时40分52秒
 ************************************************************************/

#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <map>
#include <bitset>
#include <set>
#include <vector>

using namespace std;

const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double eps = 1e-15;
typedef long long LL;
typedef pair <int, int> PLL;

double dp[100110];

double dfs(int num) {
    if (dp[num] != -1) {
        return dp[num];
    }
    int cnt = 2;
    double ans = 0;
    for (int i = 2; i * i <= num; ++i) {
        if (num % i == 0) {
            ++cnt;
            ans += dfs(num / i);
            if (num / i != i) {
                ans += dfs(i);
                ++cnt;
            }
        }
    }
    ans += cnt;
    ans /= (cnt - 1);
    return dp[num] = ans;
}

int main() {
    int t;
    scanf("%d",&t);
    int icase = 1;
    while (t--) {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) {
            dp[i] = -1;
        }
        dp[1] = 0;
        printf("Case %d: %.12f\n", icase++, dfs(n));
    }
    return 0;
}
时间: 2024-10-26 10:15:36

LIghtOJ1038---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

Codeforces 28C [概率DP]

/* 大连热身D题 题意: 有n个人,m个浴室每个浴室有ai个喷头,每个人等概率得选择一个浴室. 每个浴室的人都在喷头前边排队,而且每个浴室内保证大家都尽可能均匀得在喷头后边排队. 求所有浴室中最长队伍的期望. 思路: 概率dp dp[i][j][k]代表前i个浴室有j个人最长队伍是k的概率. 枚举第i个浴室的人数.然后转移的时候其实是一个二项分布. */ #include<bits/stdc++.h> using namespace std; int jilu[55]; double dp[

hdu 3076 ssworld VS DDD (概率dp)

///题意: /// A,B掷骰子,对于每一次点数大者胜,平为和,A先胜了m次A赢,B先胜了n次B赢. ///p1表示a赢,p2表示b赢,p=1-p1-p2表示平局 ///a赢得概率 比一次p1 两次p0*p1 三次 p0^2*p1,即A赢的概率为p1+p*p1+p^2*p1+...p^n*p1,n->无穷 ///即a_win=p1/(1-p);b_win=p2/(1-p); ///dp[i][j]表示a赢了j次,b赢了i次的概率 ///dp[i][j]=dp[i-1][j]*b_win+dp[

hdu 3853 概率DP 简单

http://acm.hdu.edu.cn/showproblem.php?pid=3853 题意:有R*C个格子,一个家伙要从(0,0)走到(R-1,C-1) 每次只有三次方向,分别是不动,向下,向右,告诉你这三个方向的概率,以及每走一步需要耗费两个能量,问你走到终点所需要耗费能量的数学期望: 回头再推次,思想跟以前的做过的类似 注意点:分母为0的处理 #include <cstdio> #include <cstring> #include <algorithm>

hdu4089(公式推导)概率dp

题意:有n人都是仙剑5的fans,现在要在官网上激活游戏,n个人排成一个队列(其中主角Tomato最初排名为m), 对于队列中的第一个人,在激活的时候有以下五种情况: 1.激活失败:留在队列中继续等待下一次激活(概率p1) 2.失去连接:激活失败,并且出队列然后排到队列的尾部(概率p2) 3.激活成功:出队列(概率p3) 4.服务器瘫:服务器停止服务了,所有人都无法激活了(概率p4) 求服务器瘫痪并且此时Tomato的排名<=k的概率. 解法:ans[i][j]表示i个人出于第j个位置要到目的状

poj3071(概率DP)

题意:淘汰赛制,2^n(n<=7)个队员.给出相互PK的输赢概率矩阵.问谁最有可能赢到最后. 解法:ans[i][j]表示第i个队员第j轮胜出的概率.赢到最后需要进行n场比赛.算出每个人赢到最后的ans[i][n].写出序号的二进制发现一个规律,两个队员i.j如果碰到,那么一定是在第get(i,j)场比赛碰到的.get(i,j)计算的是i和j二进制不同的最高位,这个规律也比较明显. 代码: /****************************************************

【Foreign】开锁 [概率DP]

开锁 Time Limit: 10 Sec  Memory Limit: 256 MB Description Input Output Sample Input 4 5 1 2 5 4 3 1 5 2 2 5 4 3 1 5 3 2 5 4 3 1 5 4 2 5 4 3 1 Sample Output 0.000000000 0.600000000 0.900000000 1.000000000 HINT Main idea 一个宝箱内有一个可以开启别的宝箱的钥匙,可以选择k个宝箱,询问能开

POJ 2151 Check the difficulty of problems (概率DP)

题意:ACM比赛中,共M道题,T个队,pij表示第i队解出第j题的概率 ,求每队至少解出一题且冠军队至少解出N道题的概率. 析:概率DP,dp[i][j][k] 表示第 i 个队伍,前 j 个题,解出 k 个题的概率,sum[i][j] 表示第 i 个队伍,做出 1-j 个题的概率,ans1等于, T个队伍,至少解出一个题的概率,ans2 表示T个队伍,至少解出一个题,但不超过N-1个题的概率,最后用ans1-ans2即可. 代码如下: #pragma comment(linker, "/STA

UVALive 6672 Bonus Cards 概率dp

题意呢 就是有两种售票方式 一种是icpc 一种是其他方式 icpc抢票成功的概率是其他方式的2倍…… 这时 一个人出现了 他通过内幕知道了两种抢票方式各有多少人 他想知道自己如果用icpc抢票成功的概率是多少 用acm抢票成功的概率是多少…… 做过不多的概率dp 还在摸索…… dp[i][j]代表第i轮有j个icpc的人已经有票了…… 当然同时i-j个通过其他方式抢票的人也有票了 这就是用同样的函数搜两次的原理…… 优化一次i<=a 一次是把初始化放到for里…… 第一次见这么卡时间的题……

HDU 4599 Dice (概率DP+数学+快速幂)

题意:给定三个表达式,问你求出最小的m1,m2,满足G(m1) >= F(n), G(m2) >= G(n). 析:这个题是一个概率DP,但是并没有那么简单,运算过程很麻烦. 先分析F(n),这个用DP来推公式,d[i],表示抛 i 次连续的点数还要抛多少次才能完成.那么状态转移方程就是 d[i] = 1/6*(1+d[i+1]) + 5/6*(1+d[1]), 意思就是说在第 i 次抛和上次相同的概率是1/6,然后加上上次抛的和这一次,再加上和上次不同的,并且又得从第1次开始计算. 边界就是