思路一:
计算出n!= nValue,然后 nValue % 10 == 0 则nCount自增1,nValue /= 10 直到条件为否,最后nCount就是我们想要的结果,代码如下:
1 int CountZero(int n) 2 { 3 unsign long long nValue = 1; 4 for (int i = 2; i <= n; i ++) 5 { 6 nValue *=i; 7 } 8 int nCount = 0; 9 while(0 == nValue % 10)10 {11 nCount ++;12 nValue /= 10; 13 }14 return nCount;15 }
代码简洁易懂,看上去还不赖,但是这里要考虑一个问题就是在求n!整数溢出了怎么办? 显然我们使用_int64也同样会有溢出的时候,所以上面的代码实际上是不可行的。
思路二:
不知道怎么办,不妨先举例分析:
1! = 12! = 1 * 2 = 23! = 1 * 2 *3 = 64! = 1 * 2 * 3 * 4 = 245! = 1 * 2 * 3 * 4 * 5 = 120........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
我们会发现一个因子2和因子5组合产生一个0,这样我们只需统计1到n有多少个因子对,即n!的尾随零个数,因子2的个数比因子5的个数多,因此我们只需统计出因子5的个数即可,如
5,10,15,25,30,35,40.......
需要注意的是,以100!为例:
统计一次5的倍数 (5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100)= 20
统计一次25的倍数(因为25的倍数有两个5的因子,所以再统计一次)(25,50,75,100) = 4
统计一次125的倍数(125的倍数由3个5的因子,所以再统计一次,以此类推)(nil)
所以100!的尾随零个数为24个
实现代码如下:
1 int CountZero(int n)2 {3 int count = 0;4 if (n < 0)5 return -1;6 for (int i = 5; n / i > 0; i *= 5)7 count += n / i;8 return count;9 }
运行结果:
1 1 0 02 2 0 03 6 0 04 24 0 05 120 1 16 720 1 17 5040 1 18 40320 1 19 362880 1 110 3628800 2 211 39916800 2 212 479001600 2 213 6227020800 2 214 87178291200 2 215 1307674368000 3 316 20922789888000 3 317 355687428096000 3 318 6402373705728000 3 319 121645100408832000 3 320 2432902008176640000 4 421 14197454024290336768 0 422 17196083355034583040 1 423 8128291617894825984 0 424 10611558092380307456 0 4
当n=21时,21!已经溢出。