【问题标题】:Finding last digit of sum from m to n Fibonacci numbers. (0 ≤ ???? ≤ ???? ≤ 10^14)从 m 到 n 斐波那契数中查找总和的最后一位。 (0 ≤ ???? ≤ ???? ≤ 10^14)
【发布时间】:2020-09-04 13:16:33
【问题描述】:

我的代码如下:

m, n = map(int, input().split())

# write function "fibtotal" which takes input x and gives accurate fib(x+2)%10  (as sum till fib(x) == fib(x+2) - 1)
# using above function get fibtotal(m-1) and fibtotal(n)
# subtract fibtotal(m-1) from fibtotal(n) and do mod 10 gives last digit of sum from m to n
# take care of handling large input sizes, 0 ≤ ???? ≤ ???? ≤ 10^14

def fibtotal(x):

  sum = 1 # if both initial conditions fail then loop starts from 2

  x= x % 60 # pisano period of 10 is 60 and to get last digit we need to divide by 10

  if x == 0:
    sum = 1 # fib(2)
    return sum 

  if x == 1:
    sum = 2 # fib(3)
    return sum

  a, b = 0, 1

  for i in range(2, x+3): # to find sum till fib(x+2)

    c = (a+b)%10
    sum += c
    a, b = b%10, c%10

  return sum%10

# no need to subtract 1 from both as they cancel out
print(fibtotal(n)-fibtotal(m-1))

以下案例使用此算法失败:

10 10 我的输出:4,正确输出:5

10 200 我的输出:5,正确输出:2

1234 12345 我的输出:2,正确输出:8

(可能还有更多)

我想知道问题出在哪里以及如何解决? 有没有更好的方法使用相同的基本原理?

【问题讨论】:

  • 这是从哪里来的?看起来像是 HackerRank 问题或类似问题。

标签: python algorithm fibonacci fibonacci-heap


【解决方案1】:

循环数有问题:你在应该有x的地方做了x+1个循环。而且我不明白你为什么不以sum = 0开头。

然后,您可以利用周期在恒定时间内计算总和,而无需任何循环。 aux 列表是使用 fibtotal1 计算的。

def fib(n):
    a, b = 0, 1
    for i in range(n):
        a, b = b, a + b
    return a

def fibtotal1(n):
    return sum(fib(k) % 10 for k in range(n + 1)) % 10

def fibtotal2(n):
    s, a, b = 0, 0, 1
    for i in range(n % 60):
        a, b = b, a + b
        s += a
    return s % 10

aux = [0, 1, 2, 4, 7, 2, 0, 3, 4, 8, 3, 2, 6, 9, 6, 6, 3, 0, 4, 5,
       0, 6, 7, 4, 2, 7, 0, 8, 9, 8, 8, 7, 6, 4, 1, 6, 8, 5, 4, 0,
       5, 6, 2, 9, 2, 2, 5, 8, 4, 3, 8, 2, 1, 4, 6, 1, 8, 0, 9, 0]

def fibtotal3(n):
    return aux[n % 60]

print(all(fibtotal1(n) == fibtotal2(n) == fibtotal3(n) for n in range(1000)))

另请注意,在您的最后一步中,由于计算 mod 10,差异可能是负数,因此应该是:

def fibtotal(m, n):
    return (fibtotal3(n) - fibtotal3(m - 1)) % 10

对于路过的读者:fibtotal2fibtotal3 有效,因为 fib(n) % 10 是周期性的,周期为 60,周期元素的总和是 10 的倍数。请参阅 Math.SE 上的 Fibonacci's final digits cycle every 60 numbers .

【讨论】:

  • 我一直循环到 x+3 因为总和直到 fib(x) = fib(x+2) - 1,我无法理解为什么会失败。感谢您提供更好的方法并指出错误
【解决方案2】:

正如上面提到的让-克劳德,有两个主要错误

没有。循环运行的次数

理想情况下,循环应该运行 x 次(包括条件),但我将它与 sum(fib(0 to x)) = fib(x+2) -1 混淆并让它运行 x+2 次​​p >

在很多地方都不需要 %10

唯一需要 mod 10 的地方是显示最终结果时的最后一条语句。这个错误的原因是过于关注处理大输入大小,但他们已经在处理x%60

同样的修正代码如下:

m, n = map(int, input().split())


def fibtotal(x):

  sum = 1 # if both initial conditions fail then loop starts from 2

  x= x % 60 # pisano period of 10 is 60 and to get last digit we need to divide by 10

  if x == 0:
    sum = 1 # fib(2)
    return sum 

  if x == 1:
    sum = 2 # fib(3)
    return sum

  a, b = 0, 1

  for i in range(2, x+1): # to find sum till fib(x+2)

    c = a+b
    sum += c
    a, b = b, c

  return sum

# no need to subtract 1 from both as they cancel out
print((fibtotal(n)-fibtotal(m-1))%10)

注意:如果 m > 1,则值“sum”无关紧要,因为它在最后减去时会抵消

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-20
    • 2017-01-29
    • 1970-01-01
    • 2019-05-29
    • 1970-01-01
    • 2020-08-26
    • 2020-05-24
    • 1970-01-01
    相关资源
    最近更新 更多