有关阶乘的算法,不外乎两个方面:一是高精度计算;二是与数论相关。
一. 高精度计算阶乘
这实际上是最没有技术含量的问题,但是又会经常用到,所以还是得编写,优化它的计算。
首先看小于等于12的阶乘计算(计算结果不会超出32位范围):
int factorial(int n)
{
if (n == 1 || n == 0) return 1;
return factorial(n-1)*n;
}
这个递归程序简单明了,非常直观,然而一旦n > 12,则超过32位int型的范围出现错误结果,所以上面这个递归程序仅适合n <= 12的阶乘计算,为了计算较大n的阶乘,需要将高精度乘法算法纳入到阶乘计算中来,高精度乘法过程可以如下简单的描述:(其中A * B = C,A[0], B[0], C[0]分别存储长度)
for (i = 1; i <= A[0]; i++)
for (j = 1; j <= B[0]; j++) {
C[i+j-1] += A[i]*B[j]; // 当前i+j-1位对应项 + A[i] * B[j]
C[i+j] += C[i+j-1]/10; // 它的后一位 + 它的商(进位)
C[i+j-1] %= 10; // 它再取余即可
}
C[0] = A[0] + B[0];
while (C[0] > 1 && C[C[0]] == 0) C[0]--; // 去头0,获得实际C的长度
有了这个高精度乘法之后,计算阶乘就可以简单的迭代进行:
for (i = 2; i <= n; i++) {
将i转换成字符数组;
执行高精度乘法:将上一次结果乘上i
}
二. 与数论有关
由于阶乘到后面越来越大,巧妙的利用数论求得一些有趣的数字(数值)等成为阶乘算法的设计点,下面给出几道相关的问题与分析:
(1) 计算阶乘末尾第一个非0数字:
例1.阶乘的最后一个不为0的数 蓝桥杯
题目描述: 一个整数n的阶乘可以写成n!,它表示从1到n这n个整数的乘积。阶乘的增长速度非常快,例如,13!就已经比较大了,已经无法存放在一个整型变量 中;而35!就更大了,它已经无法存放在一个浮点型变量中。因此,当n比较大时,去计算n!是非常困难的。幸运的是,在本题中,我们的任务不是去计算 n!,而是去计算n!最右边的那个非0的数字是多少。例如,5! = 12345 = 120,因此5!最右边的那个非0的数字是2。再如:7! = 5040,因此7!最右边的那个非0的数字是4。请编写一个程序,输入一个整数n(n<=100),然后输出n! 最右边的