Number Length
Problem description |
N! (N factorial) can be quite irritating and difficult to compute for large values of N. So instead of calculating N!, I want to know how many digits are in it. (Remember that N! = N * (N - 1) * (N - 2) * ... * 2 * 1) |
Input |
Each line of the input will have a single integer N on it 0 < N < 1000000 (1 million). Input is terminated by end of file. |
Output |
For each value of N, print out how many digits are in N!. |
Sample Input |
1 3 32000 1000000 |
Sample Output |
1 1 130271 5565709 看到求阶乘的题目,第一反应就是用递归了,可是注意到这里的输入范围是1~1000000,而在32位系统中(现在基本上int都是32位),范围-2147483648~+2147483647。unsigned类型 的int 范 围:0~4294967295 即 0~(2的32次方-1),所以用递归把阶乘结果计算出来以后再算位数是会越界的,除非用数组保存阶乘结果,但感觉略麻烦。这里我用了3种方法来计算阶乘的位数: 方法一:直接利用公式计算阶乘结果以及位数:对于数n求位数:log10(n)+1即可,只要注意的是,<math.h>中log10(n)的返回值是double,所以要转换成int。 int main()
方法二:利用迭代,原本计算公式应该是(n*(n-1)*...*2*1)/(10*10*...*10),计算能除多少个10,结果再加1.现在是从第一个n开始就除10,判断能否除完以后的结果>1,如果大于1,就result++, 把结果继续乘(n-1),再除10,同样计算;如果不能除10,就乘以(n-1)后再判断。 方法三:使用动态规划的思想,提高速率。将1000000个结果都先保存在result[1000000]数组中,根据log10(n*(n-1)*(n-2)*...*2*1)=log10(n)+log10(n-1)+...+log10(2)+log10(1)的公式, 直接计算出阶乘的位数,所以result[n] = result[n-1]+log10(n); double result[1000000];//全局变量 void add(int n) { 其实一开始这三种方法怎么试都通不过学校ACM的测试器,一直报超时,困惑了很久,发现原来是死在了输入上! 原先所有方法的循环输入我是这么写的: while(scanf("%d",&n)&&n!=EOF) 但是正确的输入应该是: while(scanf("%d",&n)!=EOF) 错误出现在哪里使他死循环了呢? 当读到输入文件的末尾,scanf会返回EOF。scanf要么返回1(成功匹配input),要么返回-1(读到文件末尾),EOF在C的头文件里面是一个宏, 通常的值为-1,但是如果写成n!=EOF,我输入的n的确是永远都不会是-1的,因为输入在1~1000000,也就是当我到达输入文件的末尾时,&&的左右 两项都不会为0,while()内的条件永真,死循环---->超时!
|