(1)给定一个整数N,那么N的阶乘N!末尾有多少个0?比如:N=10,N!=3628800,N!的末尾有2个0。
(2)求N!的二进制表示中最低位为1的位置。
0的个数
首先考虑哪些组合可以得到10即可,考虑哪些数相乘能得到10,N!= K * 10M其中K不能被10整除,则N!末尾有M个0.
对N!进行质因数分解: N!=2X3Y5Z…,因为10=2*5,所以M与2和5的个数即X、Z有关。每一对2和5都可以得到10,故M=min(X,Z)。因为能被2整除的数出现的频率要比能被5整除的数出现的频率高,所以M=Z。
<pre><code>` func compute1(num:Int) -> Int {
var count:Int = 0
for i in 1...num {
var j:Int = i
while j % 5 == 0 {
count += 1
j /= 5
}
}
return count
}`</code></pre>
第二种解法 Z =[N/5] + [N/52] + [N/53] + …
[N/5] 表示不大于N的的数中5的倍数贡献一个5, [N/52] 表示不大于N的数中52的倍数在贡献一个5……
<pre><code>` func compute2(num:Int) -> Int {
var count:Int = 0
var temp:Int = num
while temp > 0 {
count += temp / 5
temp /= 5
}
return count
}`</code></pre>
最低位1的位置
将二进制数字除以2,若是余数是0则为偶数,余数是非0则是奇数,余数即为最后一位的代表的值.所以判断N!的二进制表示中最低位为1的位置的问题可以转换为求N!中含有质因数2的个数的问题。即位置为N!含有质因数2的个数加1.
N!中含有质因数2的个数等于:[N/2]+[N/4]+[N/8]+…
<pre><code>func lowestOne(num:Int)->Int { var count:Int = 0 var temp:Int = num while temp > 0 { temp >>= 1 count += temp } return count }
</code></pre>
两个问题类似,问题1的第一种解法同样适用于第二种:
<pre><code>` func lowestOne1(num:Int) -> Int {
var count:Int = 0
for i in 1...num {
var j:Int = i
while j % 2 == 0 {
j /= 2
count += 1
}
}
return count
}`</code></pre>
测试代码:
<pre><code>`var result1 = factorial.compute1(num: 20)
print("FlyElephant-10进制0的个数---(result1)")
var result2 = factorial.compute2(num: 20)
print("FlyElephant-10进制0的个数---(result2)")
var result3 = factorial.lowestOne(num: 10)
print("FlyElephant-1的位置---(result3)")
var result4 = factorial.lowestOne1(num: 10)
print("FlyElephant-1的位置---(result4)")`</code></pre>
题外话,判断数字是不是2的整数次幂?
<pre><code>func isPowerOfBinary(num:Int) -> Bool { return num > 0 && (num & (num - 1)) == 0 }
</code></pre>