求N!末尾0的个数

本文探讨如何高效地计算一个整数N的阶乘N!末尾0的个数。通过分析N!的因数分解,发现只需关注2和5的个数,特别是5的个数,因为2的个数总是大于5的。方法一是优化循环条件,从1开始每隔5个数检查;方法二是通过累加N除以5的整数部分及其更高次幂的整数部分。这种方法类比于求二进制中末尾0的个数,进一步优化了计算效率。

题目:给定一个整数N,那么N的阶乘N!末尾有多少个0呢?例如:N=10,N!=3 628 800,N!的末尾有两个0。


方法一:

最容易想到的方法,先把N的阶乘求出来,再用一个函数计算末尾0的个数,但是这个方法有两个问题:当数字很大时,效率很差、用内置类型(int、long等)会溢出。要解决这两个问题,只能优化算法。

首先要知道N的阶乘一定可以用K×10M来表示,那我们的问题就变成了求M。又因为10 只能分解成 2 * 5,所以只需要求出 2 的个数和 5 的个数中的最小值,就得到了M。 而任何数因数分解后,2 的个数 一定多于 5 的个数(因为2的倍数比5的倍数多),所以 这个题最后又变成 了求 5 的个数。

可知 5 的倍数一定是隔 5 个数字出现一次,那么就可以修改一下循环条件不需要从1开始。

int NumOf0(int n){
	int num = 0;
	for (int i = 5; i <= n; i += 5){
		int j = i;
		/*每除得一个5,就说明末尾有一个0*/
		while (j % 5 == 0){
			num++;
			j /= 5;
		}
	}
	return num;
}

方法二:

上面得到了结论:求出 5 的个数就是末尾0的个数。随着数字的增加,能提取出来的 5 的个数越来越多,循环次数会增加,为了减少循环次数,我们可以提取5 , 5^2, 5^3 ……可以提高效率5 的个数 Y 可得到公式:Y = [N/5] + [N/52] + [N/53] + …

int NumOf0_fast(int n){
	int num = 0;
	
	while (n != 0){
		num += n / 5;
		n /= 5;
	}
	
	return num;
}

类似问题:求N!的二进制表示中最低位1的位置。

  这个问题相当于求N!的二进制中末尾0的个数,而对于二进制来说每乘2就会有一个0。所以问题又变成了求N!中 2 的个数。方法和上面相同,只需要把代码中的5换成2 就可以。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值