先上笨方法
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
可以移除无关项后优化为:
这里 p 是最接近 n 的且比 n 小的5的倍数,此时右边一共多少项呢?明显是p/5项,其实也就是n/5项sum = 5*10*15*...*p
这时右边的n/5项元素中的每个元素都是5的倍数,那么我们对每个元素都除一次5,一共除了n/5次,即 sum = sum / 5^(n/5),得到结果
sum = 1*2*3*4*5*...*(n/5)
结果 sum 又变成了一个阶乘即 (n/5)! ,里面又有5的倍数,我们依然可以原样优化:
这里 q 是最接近n/5 的且比 n/5 小的5的倍数,此时右边一共有 n/5/5 项元素sum = 5*10*15*...*q
我们依然可以把右边每项元素都除以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;
}
结束