有关阶乘的算法

题目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 being calculated:\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 the factorial 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

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值