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\n", 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\n", len);
    }
    return 0;
}

 

posted @ 2013-12-14 17:25  斐儿不一般  阅读(204)  评论(0编辑  收藏  举报