题目1:给定一个整数N,那么N的阶乘N!末尾有多少个0呢?例如:N=10,N!=3 628 800,N!的末尾有两个0。
初看这样的题目可能会想到直接求出N!的阶乘,然后再计算出0的个数。
显然用这种方法如果N很大的情况下,非常容易溢出。所以我们可以换个角度来分析这个问题。N=1×2×3×4×5×6×··· ×N我们可以对N!进行分解质因数 即N!=2x ×3y ×5z ··········可以看到2和5相乘必然会产生一个10,而这个10会在阶乘的末尾添加一个0。那么问题就转化为2x ×5z 可以产生多少个0,即min(x,z),显然X肯定大于Z(能被2整除的数肯定比5多),最终问题转化为求Z的值-即找出1...N能分解出多少个5, 程序如下:
int countFactorialZero(int N) { int ret = 0, i, j; for (i = 1; i <= N; i++) { j = i; while (j % 5 == 0) { ret++; j /= 5; } } return ret; }
题目2:求N!的二进制表示中最低位1的位置。
问题2要求的是N!的二进制表示中最低位1的位置。给定一个整数N,求N!二进制表示的最低位1在第几位?
例如:给定N= 3,N!= 6,那么N!的二进制表示(1 010)的最低位1在第二位。
为了得到更好的解法,首先要对题目进行一下转化。
首先来看一下一个二进制数除以2的计算过程和结果是怎样的。
把一个二进制数除以2,实际过程如下:
判断最后一个二进制位是否为0,若为0,则将此二进制数右移一位,即为商值(为什么);反之,若为1,则说明这个二进制数是奇数,无法被2整除(这又是为什么)。 所以,这个问题实际上等同于求N!含有质因数2的个数。即答案等于N!含有质因数2的个数加1。
int lowestOne(int N) { int Ret = 0; while (N) { N >>= 1; Ret += N; } return Ret; }