求n!尾部包含0的个数

来源:互联网 发布:mac怎么清理系统垃圾 编辑:程序博客网 时间:2024/04/28 19:25

 题目: 对任意输入的正整数N,编写C程序求N!的尾部连续0的个数,并指出计算复杂度。如:18!=6402373705728000,尾部连续0的个数是3。  (不用考虑数值超出计算机整数界限的问题) 

 

先考虑一种简单的情况, x * y 的尾部有几个0?

一个简单的方法就是先求出z=x*y的值, 再去查探z尾部有多少个0.

但是如果x * y的值很大, 导致z溢出呢?

把x分解为(x1 * x2 *x3 * x4 ... xn), y分解为(y1 * y2 * y3 * y4 * ...ym), 我们假设对x,y分解得比较恰当, 使得xi后面的数和yj后面的数怎样相乘都不会产生0, 而xi前面的数和yj前面的数都找到一对数使得其积为10.

比如, x = 35, y =8, 则可以分解为x =(5 * 7), y = (2 * 2 * 2), x1*y1 = 10, 而他们后面的数无论怎样相乘都不会得出有0结尾的数.

于是, 整个x * y尾部0的个数就是xi前面的数和yj前面的数的配对数, 在上例中为1对.

可以证明, 在所有素数中, 只有2*5的尾数为0, 其它无论怎样相乘都不会得出结尾为0的数.

所以, 该求x * y 的尾部0的个数可以这样解: 把x, y分解质因数, 再求这些质因数中2和5配对的个数, 即为尾部0的个数.

 

对于n!进行质因数分解时, 2的个数必定比5的个数多,因为

5^1=5; 5^2=25; 5^3=125...

2^1=2; 2^2=4;   2^3=8   ...

要使得a!中的5的个数比b!中2的个数多时, a必须要比b大很多.

 

所以, 其实我们只需要算出n!中质因数5的个数即可得出尾部0的个数了, 求n * (n - 1) * (n - 2) ... * 1中含有5的个数方法如下:

设含有5的个数为k, 则

k = n/5 + n/25 + n / 125 ... + n / 5i      (i = log5(n))

可知k为一等比数列, 可得k = (n/5)(1-(1/5)i)/(1-1/5)

故输入n, 可以通过公式直接得到结果k.

原创粉丝点击