码迷,mamicode.com
首页 > 其他好文 > 详细

LightOJ 1038 - Race to 1 Again(期望+DP)

时间:2016-08-10 17:32:00      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://lightoj.com/volume_showproblem.php?problem=1038

题意是:给你一个N (1 ≤ N ≤ 105) 每次N都随机选一个因子d,然后让N=N/d, 求N变成1的次数的期望;

 

当 N = 2 时 2有两个因子:1,2

E[2] = E[1]/2 + E[2]/2 + 1;因此可以求出E[2];

当N = 8 时 8有4个因子1 2 4 8;

E[8] = E[1]/4 + E[2]/4 + E[4]/4 + E[8]/4+ 1;因此可以求出E[8];

......

我们用 E[i] 表示 i 变成 1 的次数期望;那么E[i] = E[a[1]]/cnt + E[a[2]]/cnt + ... + E[a[cnt]]/cnt + 1;(加1是因为本次除了一次);

其中cnt为 i 的因子个数,a数组为 i 的因子集合,如果按从小到大的顺序排列 则 a[1] = 1, a[cnt] = i;

所以上式中的a[cnt]替换为i;整理可得 E[i] = (E[a[1]]+E[a[2]]+ ... +E[a[cnt-1]]+cnt)/(cnt-1);

 

技术分享
#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
using namespace std;
#define N 100005
#define met(a, b) memset(a, b, sizeof(a))
#define MOD 110119

typedef long long LL;

double dp[N];

void Init()
{
    dp[1] = 0;
    for(int i=2; i<N; i++)
    {
        double sum = 0;
        int cnt = 0;
        for(int j=1; j*j<=i; j++)
        {
            if( i%j == 0 )
            {
                cnt++;
                sum += dp[j];
                if(j*j != i)
                {
                    cnt ++;
                    sum += dp[i/j];///j是i的因子,i/j也是i的因子;
                }
            }
        }
        sum += cnt;
        dp[i] = sum/(cnt-1);
    }
}

int main()
{
    Init();
    int T, t = 1, n;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        printf("Case %d: %.6f\n", t++, dp[n]);
    }
    return 0;
}
View Code

 

LightOJ 1038 - Race to 1 Again(期望+DP)

标签:

原文地址:http://www.cnblogs.com/zhengguiping--9876/p/5757576.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!