HDU 1124 Factorial 求阶乘末尾的零的个数

        这是给大一第四周出的作业题中的一道,由于没有开例会,所以在这里详细的解释一下,以发到公众号推送上面去XDD  如果有误请多多包涵quq,并且能指出来的话感激不尽。

     如果想要学习本题思想解法请阅读全文,如果只是想要代码请直接拉到最后方位置。


1.题目描述

(省略原文一大段)总的来说就是求阶乘后末尾的零的个数。

2.解题思路

        正常情况肯定想到的是先直接求阶乘然后取它末尾的零,但这种办法对于小数阶乘还好办,数据如果很大了就完全没有办法;如果是大数阶乘取数组从前往后为0的数目的话用的时间和空间也特别的多,因为要先做一次阶乘然后再取,因此思考后发现可以采用数学的方法来做。

        一提到阶乘末尾有零的数首先想到的就是5!=120,而我们也知道一个数一旦末尾有了零,那么它不管乘以任何数,得到的结果都至少含有原来个数的零,而这也是这道题的突破点。因此我们5为步长,所有的操作都是在5!的基础上进行。可能这时候会有几个问题:(1)为什么不考虑10。因为以10为步长的话,像5,15,25这一类的数字计算起来就很麻烦;(2)为什么不考虑2*5,分开求2和5的公倍数然后相乘。这个办法是可以解决5(2*0+5*1),15(2*0+5*3)之类的问题,但是仔细想想要这样分开实现也是很麻烦的,同时还要考虑2个数各自的取值问题。

       因此我们可以得到,凡是阶乘末尾有零的必定是由“由5乘以某个偶数得来的”,所以实际上那些末尾有零的数满足以下要求:阶乘里面的数(如3!里面有1,2,3)有5或5与某个数的乘积(如10,15)。

       寻找方法如下:

       例如,在100中,有5,10,15,20,25......90,95,100这些数:

       而5=5*1;10=5*2;15=5*3;20=5*4.。因此5!里面有1个510!里面有2个5(5!和10=2*5里面的5),15!里面有3个5(10!和15=3*5里面的5).......则因此10!末尾有2个零,15!末尾有3个零......

      这里有一个分界线,那就是25时,25里面有65(20!和25=5*5里面的2个5),因此在25之后的每个数里面都实际上会多加1个5,因此25!末尾有6个零,30!末尾有7个零......据此我们可以知道每当数除以5后的余数仍能再次除以5的话就为一个分界线,每过一次分界线后就要多加余数个5,例如25/5=5,5/5=1,它原本是5个5,所以加1之后就是6个零;50/5=10,10/5=2,它原本是10个5,所以加上2个零后就有12个......

    当下一次余数为5的时候,此时为125,为125/5=25,25/5=5,5/5=1,根据上面的“每过一次分界线后就要多加余数个5”可知它的5的个数为25+5+1=31。因此我们可以将这个部分设定为一个循环加上一个除以5的判定。

3.代码

      分析清楚过后,我们用代码表示上述的内容即为:

1    count=0;//零的个数
2    t=n/5;//n为输入的数,这一步的作用是求出含有5的个数
3    while (t!=0)//余数比5大
4    {
5        count+=t;//含有t个5就有t个零
6        t/=5;//过一次分界线;如果余数小于5就结束循环
7    }

     总的代码:

 1#include<stdio.h>
 2int main(void)
 3{
 4    long long int n;//可以求很大的数的阶乘
 5    long long int t;
 6    printf("请输入数字:\n");
 7    scanf("%lld",&n);
 8    long long int count = 0;
 9    t=n/5;
10    while (t!=0)
11    {
12        count+=t;
13        t/=5;
14    }
15    printf("末尾零的个数为:%lld\n",count);
16    return 0;
17}

     运行结果:


 

     这篇花的时间也挺久的。。熟练度还是不高,还要继续努力( ・´ω`・ )

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章