求n!的末尾0的个数,如5!=120,0的个数为1。
首先想到的是直接计算出n!的结果,然后再对结果进行求余和求整,最后得到想要的结果。但是假设n是一个足够大的数,那么n!的结果也是一个无限大的数。这样就超出int的范围,甚至long的范围。当n足够大时,此方法无效。
如果n!=k*10M,(0!=k%10),那么M就是想要的结果。同时把n!进行质解,n!=2X*3Y*5Z...,由于10=2*5,那么n!的末尾0的个数就是min(X,Z),显然n!分解之后2的个数比5多。这样,M==Z。根据分析,要计算 Z,最直接的方法,就是计算i(i =1, 2, …, N)的因式分解中5 的指数,然后求和。
方法:
public int GetNumOfZero(int n)
{
int num = 0,temp;
for (int i = 1; i <= n; i++)
{
temp = i;
while (temp % 5 == 0)
{
num++;
temp = temp / 5;
}
}
return num;
}
temp值只有是5的倍数时才执行while循环,根据这一点,可以再优化一下。
public int GetNumOfZero(int n)
{
int num = 0,temp;
for (int i =5; i <= n; i+=5)
{
temp = i;
while (temp % 5 == 0)
{
num++;
temp = temp / 5;
}
}
return num;
}
公式:Z = [N/5] +[N/52] +[N/53] + …(不用担心这会是一个无穷的运算,因为总存在一个K,使得5K > N,[N/5K]=0)。公式中,[N/5]表示不大于N 的数中5 的倍数贡献一个5,[N/52]表示不大于N 的数中52的倍数再贡献一个5...。基于这一点,还可以再优化一下。
public int GetNumOfZero(int n)
{
int num = 0;
for (int i =5; i <= n; i*=5)
{
num+=n/i;
}
return num;
}
posted on
浙公网安备 33010602011771号