• LightOJ


    题意: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
    ", ++c, f[n]);
        }
        return 0;
    }
    
    
    
    
    
    
    
    
  • 相关阅读:
    JavaScript之函数(上)
    JAVA 遍历文件夹下的所有文件(递归调用和非递归调用)<转>
    Mac配置环境变量注意点
    netty tcp拆包
    mybatis注解方式批量插入数据
    JMX超详细解读<转>
    使用EmbeddedValueResolverAware读取配置文件内容
    线程的几种状态转换<转>
    Java线程池关闭1-shutdown和isTerminated<转>
    Maven项目编译后classes文件中没有.xml问题
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/13215989.html
Copyright © 2020-2023  润新知