问题:1,求N!末尾有多少个0?
2,N!的二进制表示中最低位1的位置?
问题1的解法一:
如果N!= K×10M,且K不能被10整除,那么N!末尾有M个0。再考虑对N!进行质因数分解,N!=(2^x)×(3^y)×(5^z)…,由于10 = 2×5,所以M只跟X和Z相关,每一对2和5相乘可以得到一个10,于是M = min(X, Z)。不难看出X大于等于Z,因为能被2整除的数出现的频率比能被5整除的数高得多,所以把公式简化为M = Z。问题相当于求N!中有质因数5的个数。
解法二:Z=[N/5]+[N/5^2]+[N/5^3]……
int NumberOfFive1(int N){ int num=0; for(int i=1;i<=N;++i){ int j=i; while(j%5==0){ num++; j/=5; } } return num; } int NumberOfFive2(int N){ int num=0; while(N){ num+=N/5; N/=5; } return num; }
问题二解法一:
这个问题实际上等同于求N!含有质因数2的个数。即答案等于N!含有质因数2的个数加1。
N!中含有质因数2的个数,等于 N/2 + N/4 + N/8 + N/16 + …
也就是N!最多能整除2的多少次幂。(同问题一解法二类似)
int LowestOne(int N){ int num=0; while(N){ N>>=1; num+=N; } return num; }
解法二:N!含有的质因数2的个数,还等于N减去N的二进制表示中1的数目
扩展问题:
给定整数n,判断它是否是2的方幂(n>0&&((n&(n-1))==0))