Finding last digit of sum from m to n Fibonacci numbers. (0 ≤ 𝑚 ≤ 𝑛 ≤ 10^14)

流过昼夜 提交于 2020-05-31 04:01:04

问题


My code is as follow :

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))

Following Cases fail using this algorithm:

10 10 My output: 4, correct output: 5

10 200 My output: 5, correct output: 2

1234 12345 My output: 2, correct output: 8

(and possibly many more)

I want to know where is the problem and how can I fix it? Is there any better approach using same fundamentals?


回答1:


There is a problem in the number of loop: you do x+1 loops where there should be x. And I don't understand why you don't start with sum = 0.

Then, you can make use of the period to compute the sum in constant time, without any loop. The aux list was computed using 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)))

Note also that in your last step, due to computing mod 10 the difference may be negative, so it should be:

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

For the reader passing by: fibtotal2 and fibtotal3 work because fib(n) % 10 is periodic with period 60, and the sum of the elements of the period is a multiple of 10. See Fibonacci's final digits cycle every 60 numbers on Math.SE.




回答2:


As Jean-Claude mentioned above, there were two main errors

no. of times the loop run

Ideally, the loop should run x times(including conditions), but I confused it with sum(fib(0 to x)) = fib(x+2) -1 and made it run x+2 times

needless %10 at many places

The only place where mod 10 was necessary was at the last statement while displaying the final result. The cause of this error was too much focus on handling large input sizes but they were already handled doing x%60.

The same rectified code looks like:

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)

NOTE: the value "sum" doesn't matter if m > 1 as it cancels out while subtracting at last



来源:https://stackoverflow.com/questions/61874703/finding-last-digit-of-sum-from-m-to-n-fibonacci-numbers-0-%e2%89%a4-%e2%89%a4-%e2%89%a4-1014

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!