计算n的阶乘中有多少个k

2018/04/30 Algorithms 共 1027 字,约 3 分钟

计算n!中5的个数

1x2x3x4x5x…xn中能除多少个5,它是个乘法,可以拆成多个因数相乘,就是1x2x3x(2x2)x5x(2x3)…

也就是计算n!中有多少个末尾0,因为2的个数比5多,所以有多少个5就是有多少个2嘛

leetcode求末尾0链接

比如计算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);
}

Search

    Table of Contents