计算n!中5的个数
1x2x3x4x5x…xn中能除多少个5,它是个乘法,可以拆成多个因数相乘,就是1x2x3x(2x2)x5x(2x3)…
也就是计算n!中有多少个末尾0,因为2的个数比5多,所以有多少个5就是有多少个2嘛
比如计算n的阶乘中有多少个5,也就是计算n!中有多少个末尾0,因为2的个数比5多,所以有多少个5就是有多少个2嘛
ret = 0;
while(N) //每执行一次迭代,就求出了 有多少个 5^M 贡献5
{
ret += N / 5; //表示 1-N 中能奉献出5的数的个数
N /= 5;
}
或者
int trailingZeroes(int n) {
long long result = 0;
for (long long i = 5; n >= i; i *= 5) {
result += n / i;
}
return result;
}
理解:
看序列1 2 3 4 5 6 7 8 9 10 11 12。。里有12/5=2个5
如果是26,那就是5个5,这没错,但是多个25,就多个5,所以就是5的个数+25的个数,同理,那些能除5的也加上
计算n!中2的个数
看计算2的个数其实就是result=[n/2]+[n/4]+[n/8]….
有两种代码表示方式
假设是8! 有1 2 3 4 5 6 7 8
第一次 则它有 2 4 6 8四个具有2的质因数
第二次 2 4 6 8变为 1 2 3 4 则只有 2 4具有2的质因数
第三次 2 4 变为 1 2 则只有2 具有2的质因数
公式 f(n) = (n/2) + (n/4) + (n/8) + (n/16) + …
关于求2的个数,还可以参考我的另一个文章,关于使用n&(n-1)
求二进制表示中1的个数
while(n > 0)
{
count++;
n&=(n-1);
}
容易得出N!质因数2的个数 = [N / 2] + [N / 4] + [N / 8] + ….
下面通过一个简单的例子来推导一下过程:N = 10101(二进制表示)
现在我们跟踪最高位的1,不考虑其他位假定为0,
则在
[N / 2] 01000
[N / 4] 00100
[N / 8] 00010
[N / 8] 00001
则所有相加等于01111 = 10000 - 1
由此推及其他位可得:(10101)!的质因数2的个数为10000 - 1 + 00100 - 1 + 00001 - 1 = 10101 - 3(二进制表示中1的个数)
推及一般N!的质因数2的个数为N - (N二进制表示中1的个数)
更快
public int trailingZeroes(int n) {
return n == 0 ? 0 : n / 5 + trailingZeroes(n / 5);
}