1、如何求N的阶乘所得的数字末尾含有多少个0
分析问题:
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,
方法1、
int countFactorialZero(int N) {
int count = 0, i=0, j=0;
for(i = 1; i <= N; i++)
{
j = i;
while(j % 5 ==0)
{
++count;
j /= 5;
}
}
return count;
}
方法2、
求n!中5的个数,
举个例子 16!中的包含5的只有,15,10,5这三个数,这个三个数分别包含了 3个5,2个5,1个5,一共有6个5,
所以可以分别求出他们中5的个数再累加。
int countFactorialZero(int n)
{
int count =0;
while(n)
{
count += n/5;
n = n/5;
}
return count;
}
2、求N!的二进制表示中最低位1的位置
分析问题:
乍一看,似乎,问题二与问题一没什么关系。然而,我们换一个角度思考,二进制中最低位1后面肯定是0,那么这里求最低位1的位置,即为求最低位1后面0的个数,而这,就和问题一是一样一样的,只不过一个是十进制表,一个是二进制表示。这里,所有小于N的数中,2的倍数都贡献一个0,4的倍数再贡献一个0,以此类推。
最关键:由于二进制表示其实是以2为基的表示,每出现一个2,末尾才会有一个0。所以只要找到N!中因子2的个数。
所以,这个问题实际上等同于求N!含有质因数2的个数。即答案等于N!含有质因数2的个数加1。
由于N! 中含有质因数2的个数,等于 N/2 + N/4 + N/8 + N/16 + … ,根据上述分析,得到具体算法,如下所示:
方法1
和问题1中的方法2思路一样。
int lcoalLastOne(int n)
{
int count = 0;//求出0的个数
while(n)
{
n = n >> 1;
count += n;
}
return count+1;//返回加1、
}
方法2、
N!含有质因数2的个数,还等于N减去N的二进制表示中1的数目,然后再加1
而对于求N的二进制中1的个数,通过n=n&(n-1),累加计数器 计算出来,上一篇博客求N二进制表示中1的个数
int lcoalLastOne(int n)
{
//先计算出n中1的个数
int temp = n;
int count = 0;
while(temp)
{
++count;
temp = temp&(temp-1);
}
//返回n-1的个数 再加1
return n-count+1;
}
3、给定整数n,判断它是否为2的方幂
n的二进制表示中,如果只有一个1的话,那么该整数就是2的方幂。
那就是就该整数 最右边的1去掉,看是否==0,
即 n&(n-1) ==0, 如果等于0,就是2的方幂。