一道小题目:给出一个n,求n!可被5整除多少次

先上笨方法

int GetDivideTimes(int n, int key)
{
	int result = 0;
	int sum = 1;
	for (int i = 2; i <= n; i++)
	{
		sum *= i;
	}
	while (sum % key == 0)
	{
		sum /= key;
		result++;
	}
	return result;
}

这个解法先不说效率问题,只要n稍微大一点sum值就会溢出,所以该做法不可取,我们需要换个思路。

如果定义 sum = n! = n*(n-1)!,如果n这个数不能被5整除,那么对于我们这题来说 n! 跟 (n-1)! 就完全没有区别,所以:

sum = 1*2*3*4*5*6*7*8*9*10*11*...*n

可以移除无关项后优化为:

sum = 5*10*15*...*p

这里 p 是最接近 n 的且比 n 小的5的倍数,此时右边一共多少项呢?明显是p/5项,其实也就是n/5项

这时右边的n/5项元素中的每个元素都是5的倍数,那么我们对每个元素都除一次5,一共除了n/5次,即 sum = sum / 5^(n/5),得到结果

sum = 1*2*3*4*5*...*(n/5)

结果 sum 又变成了一个阶乘即 (n/5)! ,里面又有5的倍数,我们依然可以原样优化:

sum = 5*10*15*...*q

这里 q 是最接近n/5 的且比 n/5 小的5的倍数,此时右边一共有 n/5/5 项元素

我们依然可以把右边每项元素都除以5,然后又获得新的阶乘 (n/5/5)!,这样循环下去直到这个阶乘的最大项小于5,循环结束

此时我们统计 sum 一共做了多少次除以5的操作,就表示原始 sum 可以被 5 整除多少次

把上述的过程转换为代码,真是简单到爆:

int GetDivideTimes(int n, int key)
{
	int result = 0;
	while (n >= key)
	{
		n /= key;
		result += n;
	}
	return result;
}

结束


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值