不要被阶乘吓到

这一节有两个问题:

  1. 给定一个整数N,那么N的阶乘N!末尾有多少个0
  2. N!的二进制表示中最低位1的位置。

对于第一个问题,其实就是计算N!中有多少个质因子5,因为所有的0末尾的0都是5和偶数相乘产生的,而偶数出现的频率要远远高于5出现的频率,所以只要计算N!中又多少个5。最直接的向下面到的代码:

intFunc1(intn)

{

intcount = 0;

for(inti=n; i>0; i--)

{

inttemp = i;

while(temp % 5==0)

{

count++;

temp /= 5;

}

}

returncount;

}

上面的代码复杂度很高,要降低复杂度可以对N循环的除以5的一次方,二次方……,直到N0N!包含的5个数=N/5+N/5二次方+N/5三次方……

intFunc2(intn)

{//n/k表示了不大于n的正整数能被k整除的个数

// 对于5m次方来说分别被5的一次方到m次方统计一次,也就统计了m

intcount = 0;

while(n){

count += n/5;

n/=5;

}

returncount;

}

问题2其实就是计算N!的二进制表示中最后有几位0,也就是计算N!中含有质因数2的个数

intFunc3(intn)

{

intcount=0;

while(n)

{

count += n/2;

n/=2;

}

returncount;

}

编程之美中还提到了一个不容易察觉的规律:N!2的个数 = N-N1的个数

intOneCount(intn)

{   

intcount = 0;

while(n)

{

n &= n-1;

count++;

}

returncount;

}

intFunc4(intn){//N!中包含质因数2的个数=n-n的二进制表示中1的个数

returnn-OneCount(n);

}

相关题目:判断N是否是2的方幂,

boolis2N(intn)

{

returnn>=0&& (n&(n-1) == 0);

}

 在做这些程序的时候在网上还看到了一些比较好玩的题目,都是和位运算相关的,顺便贴一下

//比较两个数是否相等

intIsEqual(inta,intb)

{

return!(a^b);

}

//逻辑右移N

intLogicalShift(intx,intn)

{

intmask = ~((1<<31) >> (n-1));

return(x >> n) & mask;

}

//如果一个数的二进制中含有奇数个1返回1,否则返回0

intBitParity(intn)

{

intret = (n>>16)^n;

ret = (ret>>8) ^ ret;

ret = (ret>>4) ^ ret;

ret = (ret>>2) ^ ret;

ret = (ret>>1) ^ ret;

returnret & 1;

}

//完成!运算

intQuFan(intn)

{

intret = (n>>16)|n;

ret = (ret>>8) | ret;

ret = (ret>>4) | ret;

ret = (ret>>2) | ret;

ret = (ret>>1) | ret;

return(~ret) & 1;

}

原文地址:https://www.cnblogs.com/allenzhaox/p/3201805.html