关于1000!的问题

--------------------------------------------------------------------------------------------

此文章为整理资料时所看到的,并非本人所创作,想让更多的人看到,

如有侵权,请告知

-------------------------------------------------------------------------------------------- 


       前一段时间看到一个往年程序竞赛的题解, 有一个题目说的是求 100 的阶乘末尾有多少个 0. 题解中给出的讲解提到,一个数 n 的阶乘末尾有多少个 0取决于从 1 n的各个数的因子中 2 5的个数, 2的个数是远远多余 5 的个数的,因此求出 5 的个数即可. 题解中给出的求解因子 5 的个数的方法是用 n 不断除以 5, 直到结果为 0, 然后把中间得到的结果累加. 例如, 100/5 = 20, 20/5 = 4, 4/5 = 0, 则 1 到 100 中因子 5 的个数为 (20 + 4 + 0) = 24 个, 即 100 的阶乘末尾有 24 个 0. 其实不断除以 5, 是因为每间隔 5 个数有一个数可以被 5 整除, 然后在这些可被 5 整除的数中, 每间隔 5 个数又有一个可以被 25 整除, 故要再除一次, ... 直到结果为 0, 表示没有能继续被 5 整除的数了.

        今天无意间看到有人问 1000 的阶乘有几位数, 上来就用上面的方法算了一下, 249, 又读一遍题目, 才发现是求所有的位数, 想了好久也没有思路, 无奈用 Python 算了一把, 结果有 2568 位, 可是依然不知道如何计算 1000 阶乘的位数, 还好通过结果验证了末尾有 249 个 0 是正确的...

--------

        后来浏览小百合时找到了一个方法,

 

        这是在 2006 年 11 月 17 日浏览小百合时得到的,当时上不来,就暂存在我的信箱里了。

        南京大学小百合站,Algorithm 版,x->18->1 和 x->18-2。

        x->18->1:(两处红色标记是我个人加上的,怀疑原文有误,即若有 10 和 100,则前面不应有 90 和 1800)

        令结果为 x
x=log2+log3+...+log9
  +90+log1.1+log1.2+...+log9.9
  +1800+log1.01+log1.02+...+log9.99
  +3
 =∫logx dx (
210)
  +90+
10∫logx dx(1.19.9)
  +1800+
 100∫logx dx (1.019.99)
  +3
 = ...
后两次积分上限的不同是考虑到修正


x->18->2:

x=(∫log(x)dx(2--1001)+∫log(x)dx(1--1000))/2
 =((x*log(x)-∫xdlog(x))(2--1001)+(x*log(x)-∫xdlog(x))(1---1000))/2
 =2567.857000.....



我个人的想法:

 

        经过上述两个方法,我猜想求解一个数的位数可以求解该数对其基数的对数(此处是以 10为基数的),找了几个数写了写,发现可以:

        一个以 b 为基数的数 N,在以 b 为基数的计数系统中的位数 l,可以通过求 N 对 b 的对数求得。
具体为:l=floor[log b (N) + 1],即求对数,结果加 1 后向下取整。

例如:

·     length(123456789)10=floor[lg(123456789)+1]=floor[8.091514977+1]=9

·     length(100000000)10=floor[lg(100000000)+1]=floor[8+1]=9

·     length(10101)2=floor[log 2 (23) +1]=floor[4.523561956+1]=5  (10101)2=(23)10

        再回到求解 1000的阶乘的位数上,则根据上面的说明,有:(设 1000 的阶乘结果为 N)

length(N)10=floor[lg(N)+1]
          =floor[lg(1*2*3*...*999*1000)+1]
          =floor[lg1+lg2+lg3+...+lg999+lg1000+1]
          =floor[lg2+lg3+...lg999+lg1000+1]    <= lg1=0

这时问题转到了求解 lg2+lg3+...+lg999+lg1000 的累加上面。

对于这一方面我不是很清楚(高等数学基本都不记得了...),不过根据前面两篇文章,好像有:

∑(N=2..1000)lgN = ∫lgxdx (x=2..1000)


如果成立的话,则根据 lgx = lnx/ln10 有:

∫lgxdx (x=2..1000) = (1/ln10)*∫lnxdx (x=2..1000)

                  = (1/ln10)*[x*lnx - ∫xd(lnx)] (x=2..1000)

                  = (1/ln10)*[x*lnx - ∫dx] (x=2..1000)

                  = (1/ln10)*[x*lnx - x] (x=2..1000)

                 = x*(lnx - 1)/ln10 (x=2..1000)


然后由牛顿-莱伯尼茨公式可以得到:(也不知道是否能在此处应用...)

∫lgxdx (x=2..1000) = 1000*(ln1000 - 1)/ln10 - 2*(ln2 -1)/ln10

                  = [1000*(6.907755279 - 1) - 2*(0.693147181 - 1)]/ln10

                  = [1000* 5.907755279 - 2*(-0.306852819)]/2.302585093

                  = [5907.755279 - (- 0.613705639)]/2.302585093

                  = 5908.368984639/2.302585093

                  = 2565.97204707


将结果代回前面的式子:

length(N)10 = floor[2565.97204707 + 1] = 2566


原先通过 Python 计算过 1000 的阶乘,位数为 2568 位。

考虑前面推算的过程中把 x=1 时 lg1 略掉了,理论上不应产生区别,但若要是不略掉该项时,则结果变成:

∫lgxdx (x=2..1000) = 1000*(ln1000 - 1)/ln10 - 1*(ln1 -1)/ln10

                  = [1000*( 6.907755279 - 1) - 1*(0 - 1)]/ln10

                  = [1000*5.907755279 - 1*(-1)]/2.302585093
                  = [5907.755279 + 1]/2.302585093

                  = 5908.755279/2.302585093

                  = 2566.13981258

 

length(N)10 = floor[2566.13981258 + 1] = 2567


可见结果略有不同,但都与正确结果有一点小偏差,个人认为思路是正确的,方法还有待改进。同时看到第二篇引文的结果非常接近,不过我还不理解,还需在琢磨琢磨。

还要再好好看看高等数学...
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值