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

LightOJ - 1038 Race to 1 Again(期望)

时间:2020-06-30 22:37:36      阅读:58      评论:0      收藏:0      [点我收藏+]

标签:知识   lin   就是   scan   back   return   ring   tor   cpp   

题意:Rimi学到了一个关于整数的知识,就是任何大于1的整数可以被它的任何因子整除。所以,他准备玩这个特性。他选择了一个整数N,每一次,他随机的选择这个整数的因子,并且整除这个数。直到使得这个数变成1。求N到1的期望值。

分析:一个数可以被它的因子整除,那么整除完的新值也是它的因子。我们定义f[i]:i到1的期望值,那么\(f[i] = (f[num[1]] + 1 + f[num[2]] + 1 + f[num[3]] + 1 + ... + f[num[n]] + 1) / num,\)num[]数组是i的因子数组,我们可以得出num[n] = i,所以我们可以化简如下:

\(f[i] * num = f[num[1]] + f[num[2]] + f[num[3]] + ... + f[num[n]] + num\)
\(f[i] * (num - 1) = f[num[1]] + f[num[2]] + f[num[3]] + ... + num\)
\(f[i] = \frac{f[num[1]] + f[num[2]] + f[num[3]] + ...}{num - 1}\)

这道题的数N很大,不能使用记忆化搜索,因为记忆化搜索不能把所有的状态搜到,所以要预处理出所有的值。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>

using namespace std;
const int N = 100005;
double f[N];
vector<int> v[N];

int main()
{
    int t;
    scanf("%d", &t);

    //预处理出所有因子
    for(int i = 2; i < N; ++i)
        for(int j = 1; j <= i / j; ++j)
        {
            if(i % j == 0)
            {
                v[i].push_back(j);
                if(j * j != i) v[i].push_back(i / j);
            }
        }
    for(int i = 2; i < N; ++i)
    {
        int sz = v[i].size();
        for(int j = 0; j < sz; ++j)
        {
            if(v[i][j] != i) f[i] += f[v[i][j]];
        }
        f[i] = (f[i] + sz) / (sz - 1);
    }
    int c = 0;
    while(t--)
    {
        int n;
        scanf("%d", &n);
        printf("Case %d: %.6lf\n", ++c, f[n]);
    }
    return 0;
}







LightOJ - 1038 Race to 1 Again(期望)

标签:知识   lin   就是   scan   back   return   ring   tor   cpp   

原文地址:https://www.cnblogs.com/pixel-Teee/p/13215989.html

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