水题
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; }