求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 2015-09-27 16:52  会飞的金鱼  阅读(341)  评论(0)    收藏  举报