首先,这个题是要求出给定数字的阶乘结果的倒数第一个不为0 的尾数,这需要我们通过阶乘的性质归纳总结出一定的规律,其次,由于题目要求的数字较大,对于高精度的数据可以适当采用java来求解
原文链接http://blog.csdn.net/rappy/article/details/1903360
首先对数列 d [10] = {1, 1, 2, 3, 4, 1, 6, 7, 8, 9} 和
ff [10] = {1, 1, 2, 6, 4, 4, 4, 8, 4, 6}
有 d [0] * ... * d [i] % 10 = ff [i],0 <= i < 10。
对于 n < 5 直接输出 ff [n] 即可。
对于 n >= 5,例如 n = 26,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
的乘积等于
1 2 3 4 1 6 7 8 9 1 11 12 13 14 1 16 17 18 19 1 21 22 23 24 1 26
的乘积再乘上 5 10 15 20 25 的乘积,而5 10 15 20 25 的乘积等于
1~26/5 的乘积再乘上 526/5。
先考虑
1 2 3 4 1 6 7 8 9 1 11 12 13 14 1 16 17 18 19 1 21 22 23 24 1 26,
可以 10 个 10 个地分成几组。
其中 1 2 3 4 1 6 7 8 9 1,11 12 13 14 1 16 17 18 19 1 这两组数的乘积
都为 10*q + 6 的形式,两个乘积乘起来还是 10*q + 6 的形式。
而 21 22 23 24 1 26 这组数的乘积则是 10*q + ff [26%10] = 10*q + 4的形式,
因此 3 组数的乘积是 10*q + 4 的形式,这个 4 由 ff [26%10] * 6 % 10 所得。
因此 26! = (26/5)! * 526/5 * (10*q+4) = (26/5)! * 1026/5 * [(10*q+4) / 226/5],
则 26! 的最后一个非零数字为 (26/5)! * [(10*q+4) / 226/5]。
注意到除了0! 和 1!,阶乘的最后一个非零数字必为偶数,所以有一个规律:
(10*q + 2) / 2 = 10*q‘ + 6
(10*q + 6) / 2 = 10*q‘ + 8
(10*q + 8) / 2 = 10*q‘ + 4
(10*q + 4) / 2 = 10*q‘ + 2
每除以 2 四次,尾数就循环一次。因此
(10*q+4) / 226/5 的尾数即 (10*q+4) / 226/5%4,这个可以用以下代码计算:
t = ff [n % 10] * 6 % 10;
for (int i = 1; i <= n / 5 % 4; i ++)
{
if (t == 2 || t == 6) t += 10;
t /= 2;
}
计算出来的 t 即为 (10*q+4) / 2^(26/5) 的尾数,然后用 t 乘以 (26 / 5)! 的最后
一个非零数字再对 10 取模即得到 26! 的最后一个非零数字而计算 (26 / 5)! 的最后
一个非零数字可以使用递归处理。
综上,设 F(N) 为 N! 最后一个非零数字,则有以下递归式:
F(N) = ff [N] (N < 5)
F([N/5]) * ff [N的尾数] * 6
F(N) = ----------------------------------- (N >= 5)
2[N/5] % 4
因此算法的时间复杂度是 O(log5N) 的。
即使 N 达到 10100,也可以很快计算出来,不过需要使用高精度整数,整除 5 也即
乘以 2 再整除 10,而乘以 2 也即自加,整除 10 也即截掉最后一位数字。
而对 4 取模只要取最后两位数字对 4 取模即可,例如 1234 % 4 = 34 % 4 = 2。
因此实现起来相当方便。
java解决:
import java.util.*; import java.math.*; public class Main { static int [] hash = {6, 6, 2, 6, 4, 4, 4, 8, 4, 6}; static int [] one_digit_hash = {1, 1, 2, 6, 4, 2, 2, 4, 2, 8}; static BigInteger five = BigInteger.valueOf(5),four=BigInteger.valueOf(4),ten=BigInteger.valueOf(10); public static int calc(BigInteger num) { if(num.compareTo(ten)==-1) return one_digit_hash[(int)num.longValue()]; else { int mod = (int)num.divide(five).mod(four).longValue(); String str = num.toString(); int ret = hash[str.charAt(str.length()-1)-'0']; ret=ret*calc(num.divide(five)) % 10; while(mod-- >0) ret=ret*8%10; return ret; } } public static void main(String[] args) { Scanner cin =new Scanner (System.in); BigInteger num; while(cin.hasNextBigInteger()) { num=cin.nextBigInteger(); System.out.println(calc(num)); } } }
【hoj】1013just the facts,布布扣,bubuko.com
原文地址:http://blog.csdn.net/ymzmdx/article/details/36175069