zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    一题多解 —— 同时找到序列的最大值最小值
    中位数与顺序统计量
    软件开发 —— 极限编程(XP:Extreme Programming)
    一题多解 —— 二项式分布的期望和方差的计算
    C++中explicit关键字用法
    【联系】二项分布的对数似然函数与交叉熵(cross entropy)损失函数
    随机变量统计独立性的相关证明
    PowerShell管理SCOM_批量设置维护模式(下)
    导出AD用户所属组,查询AD用户(aduser)
    SQL脚本运行
  • 原文地址:https://www.cnblogs.com/conanliu/p/scnuacm2013_fresh_1006.html
Copyright © 2011-2022 走看看