• SCNUACM新生赛解题报告-1006水题


    水题

    Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)

    Total Submission(s) : 425   Accepted Submission(s) : 7

    Problem Description

    对于正整数 n, 定义函数 f(n) 为 n 的因子之和,例:f(4)=1+2+4=7.
    对于正整数 n, 定义函数 g(n) 为 f(k) 之和,其中 k 为 n 的因子,例:g(4)=f(1)+f(2)+f(4)=1+3+7=11.
    对于正整数 n, 定义函数 h(n) 为 g(n) 的阶乘的位数,例:g(4)=11, 11! = 39916800, 故 h(4)=8.
    现在,你的任务是:对于给定的正整数 n, 求 h(n).

    Input

    多测试用例!
    每行包括一个正整数 n, 1<=n<=500000.

    Output

    每行包括一个正整数 h(n).

    Sample Input

    1

    2

    3

    4

    5

    Sample Output

    1

    2

    3

    8

    4

    Author

    SCNU20102200088

    Source

    SCNUACM

    水题不水啊,这题算是比较有难度的题目之一,对于新生来说。

    我的思路并不是太难,就是保存所有算过的f和g的值。算位数的时候用的是斯特林公式。代码写得比较难看= =。

    #include <cstdio>
    #include <string.h>
    #include <math.h>
    
    const int size = 500000 + 10;
    int save[size];//f(x)
    int g[size];//g(x)
    const double PI = acos(-1.0);//PI的精确值
    
    //计算g(a)的值,保存所有算过的f和g值
    void isPrime(int a)
    {
        int mid = sqrt(a) + 1, i, div;
        int sum = 1 + a;
        g[a] = save[1];
        for(i = 2; i < mid; i++)
        {
            if(a % i == 0)
            {
                div = a / i;
                //这里用了一些技巧
                //当对一个数x进行因式分解的时候,总是存在两个数a, b
                //a, b均小于等于根号x
                //且a * b == x
                //这里,i和div就是a和b
                if(div != i)
                {//
                    sum += div + i;
                    if(save[div] == 0) isPrime(div);
                    if(save[i] == 0) isPrime(i);
                    g[a] += save[div] + save[i];
                }
                else
                {//这是a != b的情况,即不存在一个整数a的平方等于数x
                    sum += i;
                    if(save[i] == 0) isPrime(i);
                    g[a] += save[i];
                }
            }
        }
        save[a] = sum;
        g[a] += sum;
        //printf("%d:%d
    ", a, g[a]);
    }
    
    int main()
    {
        int a, len;
        memset(save, 0, sizeof(save));
        memset(g, 0, sizeof(g));
        //save数组储存的是f(x)的值
        save[1] = 1;
        save[2] = 3;
        //g数组储存的是g(x)的值
        g[1] = 1;
        g[2] = 4;
        //for(i = 2; i < size; i++) isPrime(i);
        mr = 0;
        while(~scanf("%d", &a))
        {
            //g[a] == 0意味着g还没有被算过
            if(g[a] == 0) isPrime(a);
            a = g[a];
            //斯特林公式,计算某个数的阶乘的位数
            len = ceil((a*log((double)a)-a+log(2.0*(double)a*PI)/2.0)/log(10.0));
            //斯特林公式对len=1的情况不感冒
            if(len == 0) len = 1;
            printf("%d
    ", len);
        }
        return 0;
    }
  • 相关阅读:
    集合总结(非常重要)
    day18_Map案例
    Map代码案例
    重踏学习Java路上_Day18(Map,Collections)
    TreeSet概述(源码和内部图 进行解析,包含练习案例)
    HashSet保证元素唯一性的代码体现(源码和内部图 进行解析)
    重踏学习Java路上_Day17(登录注册案例,Set集合,Collection集合总结,在集合中常见的数据结构)
    Java 泛型解析,太难了,认真读才能理解
    题解 【BZOJ4700】适者
    题解 楼房重建
  • 原文地址:https://www.cnblogs.com/conanliu/p/scnuacm2013_fresh_1006.html
Copyright © 2020-2023  润新知