【问题标题】:Finding natural numbers having n Trailing Zeroes in Factorial在阶乘中查找具有 n 个尾随零的自然数
【发布时间】:2017-10-10 05:34:35
【问题描述】:

我需要帮助解决以下问题。

给定一个整数m,我需要找到正整数n的个数和整数,使得n阶乘正好结束> m

我编写了这段代码,它工作正常并且我得到了正确的输出,但是随着数字的增加,它花费了太多时间

a = input()

while a:
 x = []
 m, n, fact, c, j = input(), 0, 1, 0, 0
 z = 10*m
 t = 10**m

 while z - 1:
  fact = 1
  n = n + 1   

  for i in range(1, n + 1):
     fact = fact * i

  if fact % t == 0 and ((fact / t) % 10) != 0:
     x.append(int(n))
     c = c + 1

  z = z - 1

 for p in range(c):
  print x[p],

 a -= 1
 print c

有人可以建议我一种更有效的方法来做到这一点。目前,一个测试用例要求在其阶乘中以 250 尾随零的数字需要 30 秒

谢谢

【问题讨论】:

    标签: algorithm python-2.7 factorial trailing


    【解决方案1】:

    要获得n!的尾随零的数量有效你可以放

    def zeroes(value):
        result = 0;
    
        d = 5;
    
        while (d <= value): 
            result += value // d; # integer division
            d *= 5;
    
        return result; 
    
    ...
    
    # 305: 1234! has exactly 305 trailing zeroes 
    print zeroes(1234) 
    

    为了解决问题(nn! 中的尾随零),您可以使用以下事实:

    • 零的数量是一个单调函数:f(x + a) &gt;= f(x) if a &gt;= 0
    • 如果f(x) = y 然后x &lt;= y * 5(我们只计算5 因素)。
    • 如果f(x) = y 然后x &gt;= y * 4(让我把这个留给你证明)

    然后实现二分查找(关于单调功能)。

    例如在250 为零的情况下,我们有初始范围来测试[4*250..5*250] == [1000..1250]。二进制搜索将范围缩小到[1005..1009]

    1005, 1006, 1007, 1008, 1009 都是数字,因此它们在阶乘中恰好具有 250 训练零

    编辑如果我(2 年后)证明最后一个猜想(见下面的 cmets),我希望不会破坏乐趣:

    因子中的每个5**n 乘以2**n 会产生10**n,因此n 为零;这就是为什么f(x)

    f(x) = [x / 5] + [x / 25] + [x / 125] + ... + [x / 5**n] + ...
    

    其中[...] 代表floor整数部分(例如[3.1415926] == 3)。让我们执行简单的操作:

    f(x) = [x / 5] + [x / 25] + [x / 125] + ... + [x / 5**n] + ... <= # removing [...]
            x / 5  +  x / 25  +  x / 125  + ... +  x / 5**n  + ... =
            x * (1/5 + 1/25 + 1/125 + ... + 1/5**n + ...) =
            x * (1/5 * 1/(1 - 1/5)) =
            x * 1/5 * 5/4 =
            x / 4
    

    到目前为止一切顺利

     f(x) <= x / 4 
    

    或者如果y = f(x) 那么x &gt;= 4 * y Q.E.D.

    【讨论】:

    • 你能告诉我为什么x &gt;= y * 4吗?无法证明...@Dmitry Bychenko
    • @fardinabir:我已经编辑了答案,我已经添加了证明
    【解决方案2】:

    关注构成数字的 2 和 5 的数量。例如150 由 2*3*5*5 组成,有 1 对 2&5,所以后面有一个零。每次增加测试数字时,尝试计算数字中有多少 2 和 5。由此,将先前的结果相加,您可以轻松知道其阶乘包含多少零。

    例如15!=15*...*5*4*3*2*1,从2开始:

    Number   2s  5s  trailing zeros of factorial
    2        1   0   0
    3        1   0   0
    4        2   0   0
    5        2   1   1
    6        3   1   1
    ...
    10       5   2   2
    ...
    15       7   3   3
    ..
    24      12   6   6
    25      12   8   8   <- 25 counts for two 5-s: 25 == 5 * 5 == 5**2
    26      13   8   8 
    ..   
    

    参考 Peter de Rivaz 和 Dmitry Bychenko 的 cmets,他们有一些很好的建议。

    【讨论】:

    • 由于 2 的数量总是多于 5 的数量,因此您可以只计算 5 并简化
    • 是的,你可能是对的。我会在我的回答中参考您的评论。
    • 别忘了数25两次125三次,一般情况下5**n - n
    • 测试:1005!..1009!250 尾随零
    • 感谢快速响应,(fact/t)%10,我已将 5s 和 2s 包括为 10=5*2,这使我免于检查 5^n,...但是阶乘部分使程序变慢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    • 2018-11-06
    • 1970-01-01
    • 2017-11-28
    相关资源
    最近更新 更多