您的位置:首页 > 编程语言 > C语言/C++

N的阶乘(N!)中的末尾有多少个0?

2015-08-12 11:11 459 查看
前段时间在《编程之美》中也遇到了该问题,昨天在做中国某IT公司的在线笔试题的时候,也遇到了该问题,不过之前一直没有完全理解这个问题的真正解决方式,昨天晚上在睡觉前才想明白(不好意思,智商让各位捉急了 T_T)。

N的阶乘(N!)中的末尾有多少个0? 如:N = 5,N! = 120.末尾有1个0.

很多人遇到该问题的时候会想办法把阶乘的结果求出来 ,然后再去数结果的末尾有多少个0,但是当N比较小的时候可以使用这种方式解决,当N比较大时,比如几百或者几千,甚至更大时,C++中的数据类型已经溢出,但是在Java中有一种专门针对大数相乘的计算方法,我们可以想象用这种方式的效率是什么情况,当然这也是一种解决方式。现在我们总结一下这个问题的解决方式:

第一种:先计算阶乘的结果,然后把末尾的0数出来(效率不高,并且会有溢出的风险)。

第二种:我们可以考虑一下,在N的阶乘中,只要末尾每出现一个0,表示在总结果中有一个10因子,而10因子可以用5*2表示,N的阶乘中每过五次才会出现一个5因子,但是每个两次就可以出现一个2因子,所以在阶乘中2因子的个数肯定比5因子的数量多;所以要找出有多少个10因子只需要找出5因子的数量就可以解决问题,那么现在问题就转换成了在N!中有多少个5因子。下面我们使用遍历方法计算,从1到N所有数字中5因子的个数。
#include <iostream>
using namespace std;

int main()
{
int N;
while (cin>>N)
{
int count=0;
int iTemp;
for (int i=1;i<=N;++i)
{
iTemp=i;
while ((iTemp%5)==0)
{
++count;
iTemp/=5;
}
}
cout<<N<<"!"<<"末尾有"<<count<<"个0"<<endl;
}

return 0;
}


第三种方法:该方法也是利用方法二中,计算5因子的个数来得出结果,但该方法不遍历所有数字。我们可以观察一组数字:

从1到,50之间包含5因子的数字的规律:

1*5=5, 2*5=10, 3*5=15, 4*5=20 ,5*5=25, 6*5=30,7*5=35, 8*5=40, 9*5=45 ,10*5= 50;(我们现在假设规律是:id*5=num)

所以在1到N的所有数字中,用N/5=n1(其中n1向下取整,如12.5时取12)就可以得出所有包含5因子的id序号个数;并且在id序列中可能还有5因子,我们就可以继续使用n1/5=n2;直到n2=0为止。这样在N较大的时候比前两种效率要高的多。闲话不多说,见代码:
#include <iostream>
using namespace std;

int main()
{
int N;
while (cin>>N)
{
int count=0;
int iTemp=N;
while (iTemp/=5)
{
count+=iTemp;
}
cout<<N<<"!"<<"末尾有"<<count<<"个0"<<endl;
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息