编程之美 2.2

(1)

阶乘确实是一个让人头疼的问题,其本身的实现很简单,它的问题在于结果膨胀式的增长会造成n!的结果的溢出。2.2给出了几种从数学角度出来的思路,可以避免上面的问题发生。

首先要清楚的一个问题就是质因数分解给定任意一个整数w,那么w一定可以分解成w=2^x * 3^y * 5^m……这种形式,这个数学理论是解决此类问题的关键。

接着分析因为10进行质因数分解的结果为 10 = 2 * 5, 所以每一对2和5相乘就会在其n!的末尾添加上一个0,因而n!末尾0的个数同2、5的对数相同,即末尾0的个数count = min(x,m);

其实分析到这里可以先得出一个解法了就是分别统计2和5的幂然后比较哪个比较小,min的值便是我们要取得值。

但是书中又讲到了一个不是定理的定理:在阶乘n!的质因数分解中2的指数不会小于5的指数。 因而这个问题直接便转化为求5的指数,具体做法很容易详情见解法一书中;

很明显解法一的时间复杂度是O(nlog5n),这个算法在很大程度上还是取决于n的大小;


解法2是一个很精彩的做法,时间复杂度优化到了O(log5n),阶乘n!中最后一个数n反应了前面数的一些基本情况,比如说21/5=4说明就是在21之前一共出现过4次5,这样就避免了遍历一遍n的时间。又比如25/5=5,这说明从1到25已经出现了5个5,且结果还是5说明25是两个5相乘得到的,所以是1+1+1+1+2=6,解法二已经是这个问题的极限优化解法。

判断n!可以被数k整除多少次?

num = [n/5] + [n/5^2] + …… + [n/5^m],n/5^m = 0


(2)

其实(1)和(2)是本质相同的两个问题,(2)就是找到在n!的质因数分解中2的指数。



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值