有关阶乘的算法

来源:互联网 发布:nginx php cgi 编辑:程序博客网 时间:2024/05/15 05:25

题目1:给定一个数n,问n的阶乘的十进制表示中末尾有几个0?

题目2:给定一个数n,问n的阶乘的二进制表示中末尾有几个0?

 

分析:题目1:此问题等价于n的阶乘包含多少个因子10.对10进行分解的2×5,则此题等价于求解n的阶乘中包含多少个因子2和多少个因子5,并取两者中中的较小值。简单分析可得n的阶乘中所包含的因子5的个数肯定比所包含的因子2的个数少,所以本题等价于求解n的阶乘中包含因子5的个数。即n的阶乘中所包含因子5的个数就是n的阶乘的十进制表示中末尾0的个数。

     题目2:相当于求n的阶乘中所包含因子2的个数。

 

解决方法:可知,能被5整除但不能被25整除的数中包含一个因子5,能被25整除而不能被125整除的数中包含2个因子5,......依此往上推。所以n的阶乘中包含因子5的个数可以这样计算:小于n且能被5整除的数的个数+小于n且能被25整除的数的个数+小于n且能被125整除的个数+......。注:能被25整除的也能被5整除,所以只是简单的加上能被25整除的数的个数而没有乘以2(25中含有两个因子5),因为前面计算能被5整除的数时已经算过一次。其他同理。

         题目2中求n的阶乘中包含因子2的个数的解放同上。

         需要注意一点:由于阶乘一般数值比较大,所以选择用long类型来存储最终的阶乘值。int类型数据最多可以表示10位的十进制数。2的31次方等于2147483648.

 

下面是题目的一个C语言实现:

#include<stdio.h>

int calculat_zero_number_at_rear(int n) //计算n的阶乘的十进制表示中末尾含0的个数
{
       int number=0;
       while(n)
       {
               number=number+n/5;
               n=n/5;
       }
       return number;
}

int main()
{
       int n,number_of_zero_at_rear,i;
       long factorial=1;  //用来存储n的factorial值
       printf("please input the number whose factorial is beingcalculated:\n");
       scanf("%d",&n);

       for(i=1;i<=n;i++)
               factorial=factorial*i;

       number_of_zero_at_rear=calculat_zero_number_at_rear(n);
       printf("the number of zero at rear of factorial of n is %d, and thefactorial of n is %ld\n",number_of_zero_at_rear,factorial);
       return 0;
}

题目2也可以用以上相同的方法求解,只是需要把程序中的5改写成2即可。题目2还有没有效率更高的解放呢?假如你知道这个特性,你就知道有更高效的方法。这个特性是:n的阶乘中所含因子2的个数等腰n减去n的二进制表示中1的个数。这样只要求得n的二进制表示中1的个数即可。n的二进制表示中所含1的个数可以参考:http://blog.sina.com.cn/s/blog_8b745a5f0101698t.html

 

 

 

 

 

 

原创粉丝点击