给定一个数N(N <= 10 ^ 1000),如何快速求得N!的最末位非零数是一个经典的问题。一直以来都被这个问题困扰,今天仔细想了下,终于给想通了,尽管可能有些笨拙,现把想法记录于此。
在N很小的情况下,有一个简便的方法:求出1到N之间每个数的2的因子数和5的因子数,记为F(2)和F(5),显然F(2) >= F(5)。由于在末尾只有2和5相乘才能产生0,如果我们把2和5抛去,那么肯定不会有0,这样就可以一边乘一边模10,防止溢出。剩下的一堆2和5如何处理呢?因为2肯定比5多,因此最末位肯定是偶数(0的阶乘和1的阶乘除外)。而一个偶数不停地乘2,最末位的规律是:2 -> 4 -> 8 -> 6 -> 2 -> ...出现了4位1循环,这样我们先用F(2) - F(5),使得一部分2和5匹配上,2 * 5 = 10,对末尾不产生影响,剩下的2就模一下4,剩几再乘几次2就可以了。
但是这个方法在N非常大的时候肯定就不行了,但是可以利用找循环这个思想继续做。如果算阶乘的时候跳过5的倍数,记G(n)为跳过5的倍数的时候,从1乘到n的最末非零位,也就是把5的倍数当1乘。可以发现:
G(1) = 1, G(2) = 2, G(3) = 6, G(4) = 4, G(5) = 4, G(6) = 4, G(7) = 8, G(8) = 4, G(9) = 6, G(10) = 6, G(11) = 6, G(12) = 2, G(13) = 6...
又出现了循环,每10个数循环一次。如何计算G(n)就变的很简单,求出n的最末位,就知道对应的G(n)是多少了,当然需要特判n = 1的情况。由于我们把5的倍数的数都提出来了,提出来的这些数(5、10、15、20、25、30...)每个除以5后又组成了一个阶乘序列!除完5一共提出了n / 5个5,根据之前的分析,每个5都可以拿出一个2和它配对然后把它消去,这样一个5就相当于少一个2,我们就要把原来的数乘以3个2(模四循环)。这样一来5的个数其实也可以模四,模完四之后剩k的话,就可以乘以k个8,就把所有的5消去了。现在总结一下:对一个数n的阶乘,计算它的末尾非零位,先计算G(n),相当于非5的倍数的数的乘积最末非零位先算好了,然后乘以n / 5 % 4个8,处理了提出的n / 5个5,这样之后还剩下n / 5的阶乘没有算。递归的求解n / 5的阶乘的最末位非零数,再乘上去就得到结果了。
这个做法的复杂度就很低了,达到O(log n),对于10 ^ 1000的数据,利用高精度做就行了。
附HOJ 1013代码:
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
2
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
3
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
4
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
5
![](https://i-blog.csdnimg.cn/blog_migrate/2f88ce130b654eb5dc6788e02dbcfc90.gif)
6
![](https://i-blog.csdnimg.cn/blog_migrate/2f88ce130b654eb5dc6788e02dbcfc90.gif)
7
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
8
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
9
![](https://i-blog.csdnimg.cn/blog_migrate/2f88ce130b654eb5dc6788e02dbcfc90.gif)
10
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
11
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
12
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
13
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
14
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
15
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
16
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
17
![](https://i-blog.csdnimg.cn/blog_migrate/f70a0fde2b51b7dd92a70e712e540cf6.gif)
18
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
19
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
20
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
21
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
22
![](https://i-blog.csdnimg.cn/blog_migrate/4a5daaec04350a363f186a4d2c5ed6ce.gif)
23
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
24
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
25
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
26
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
27
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
28
![](https://i-blog.csdnimg.cn/blog_migrate/0ac3a2d53663ec01c7f7225264eeefae.gif)
29
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
30
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
31
![](https://i-blog.csdnimg.cn/blog_migrate/2f88ce130b654eb5dc6788e02dbcfc90.gif)
32
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
33
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
34
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
35
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
36
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
37
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
38
![](https://i-blog.csdnimg.cn/blog_migrate/0ac3a2d53663ec01c7f7225264eeefae.gif)
39
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)