C语言---求n的阶乘后面有多少个连续的0

C语言---求n的阶乘后面有多少个连续的0

题目描述:给定一个正整数n,返回n的阶乘尾部连续0的个数。

例如:(5,5*4*3*2*1=120,则返回1),(10,10*9*8*7*6*5*4*3*2*1=3628800,则返回2)

 

题目分析:首先拿到这道题,直接可以想到最简单的方法就是,通过循环算出这个值,然会取个位,减个位,统计一下个数即可。但是运行后就发现不可行,因为如果n稍微大一点,则算出的这个值就太大了,保存不了,且运行超时,所以这种方法不可行。

于是就得想别的方法了,最后上网查资料发现还有一种巧妙的解法,那就是将可以造成尾部出现0的情况进行分析,发现10可以由2*5造成,发现20可以由2*2*5造成,发现100可以由2*2*5*5造成。。。

 

多试几组数据,可以发现其规律:尾部0的个数等于min{2的个数,5的个数}

因为尾部的0是由2*5得来的,虽然也可能是4*5得来的,但是4也是由2*2得来的,所以尾部的0根本上是由2*5得来的。

 

这里可以发现:一对2和5可以造成尾部一个0,n对2和5可以造成尾部n个0,但是由于2可以由太多太多的数据分解得来,所以我们这里主要看5的个数主要由哪些数分解得来即可:

比如:

5!= {1 * 2 * 3 * 4 * 5} 这里只有1个5,分别是5

10!= {1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10} 这里有2个5,分别是5,10(10是由2*5组成的)

...

25!= {1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * ... * 21 * 22 * 23 * 24 * 25} 这里有6个5,分别是 5,10,15,20,25(25是由5*5组成的,所以25算2个5

...

125!= {1 * 2 * 3 * 4 * 5 * ... * 25 * ... * 50 * ... * 75 * ... * 100 * ... * 121 * 122 * 123 * 124 * 125}这里有31个5,分别是5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,

(这里除了25,50,75,100各自是由5*5组成,算两个5,而125是由5*5*5组成的,所以125单独算三个5

 

我们可以发现每隔上5个数会出现一个5隔上25个数又单独多出来一个5隔上125个数又单独多出来两个5...

 

所以我们可以这样编写代码:

①:首先可以从1 -> n隔上5个数抽取一次,获取这些数组成一个数列

②:如果上面数列的个数>=5,就再从上面数列中再隔上5个数抽取一次,获取这些数组成一个新的数列

⑤:如果上面数列的个数>=5,就再从上面数列中再隔上5个数抽取一次,获取这些数组成一个新的数列(直到获取的数列中的数的个数小于5,则停止

 

例如求125的阶乘后面有多少连续的0:

这里用tmp统计5出现的个数

①:第一遍获取可以得到单5:{5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125},所以tmp = 25

②:因为其个数肯定 >= 5,所以进行第二遍获取可以得到5*5:{25,50,75,100,125},所以tmp = 25 + 5 = 30

③:因为其个数刚刚好 == 5,所以进行第三遍获取可以得到5*5*5:{125},

所以tmp = 25 + 5 + 1 = 31

④:因为其个数肯定 <=5,所以不进行第四遍获取,直接退出循环即可。

所以我们可以得到125的阶乘后面有31个连续的0

 

 

C语言代码如下:

#include <stdio.h>

int num(int n)
{
	if(n < 0)//只要正整数,防止负数
	{
		return -1;
	}

	int i = 0;
	int j = 5;//逐层按 5 5*5 5*5*5 进行抽取
	int count = n;//统计逐次抽出了多少个数,初始值个数为总体个数
	int tmp = 0;//统计5的个数

	while(count >= 5)
	{
		count = 0;//进来后第一件事,让其先归零,重新统计抽取个数
		i = 0;//进来后第一件事,也让i归零,因为i要从头开始遍历
		while(i + j <= n)
		{
			tmp++;
			i += j;
			count++;
		}
		j *= 5;//第一遍隔5读取   第二遍隔5*5读取,下一次就是5*5*5,依次递增
	}

	return tmp;
}

int main()
{
	printf("%d\n", num(125));
	printf("%d\n", num(25));
	printf("%d\n", num(12));
	printf("%d\n", num(0));
	printf("%d\n", num(-1));
	return 0;
}

测试一下代码,结果如下:

 

至此,这道巧妙的题解决了。

猜你喜欢

转载自blog.csdn.net/IT_Quanwudi/article/details/86729953
今日推荐