Advertisement
jules0707

fibonacci_partial_sum

Jun 13th, 2017
294
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.35 KB | None | 0 0
  1. # Uses python3
  2. import sys
  3.  
  4.  
  5. def fibonacci_partial_sum_naive(m, n):
  6.     result_sum = 0
  7.  
  8.     current_number = 0
  9.     next_number = 1
  10.  
  11.     for i in range(n + 1):
  12.         if i >= m:
  13.             result_sum += current_number
  14.  
  15.         current_number, next_number = next_number, current_number + next_number
  16.  
  17.     return result_sum % 10
  18.  
  19.  
  20. def get_fibonacci_huge_naive(n, m):
  21.     if n <= 1:
  22.         return n
  23.  
  24.     previous = 0
  25.     current = 1
  26.  
  27.     for _ in range(n - 1):
  28.         previous, current = current, previous + current
  29.  
  30.     return current % m
  31.  
  32.  
  33. #  property of the Fibonacci remainders of modulo n operation is that you can find the next remainder by adding
  34. #  the last 2 and looped on n ie. for F(13) mod 5 , r(13) = r(11) + r(12) = 4 + 4 =  3 because 8 = 5 + 3
  35. #  also the pattern of remainders repeat every time you encounter the a 0 followed by a 1. That is the mark for the
  36. #  length of the Pisano period.
  37.  
  38.  
  39. def get_fibonacci_huge_faster(p, q):
  40.     if p <= 1:
  41.         return p
  42.  
  43.     previous = 1
  44.     current = 1
  45.     pisano_period = 1
  46.  
  47.     while (previous, current) != (0, 1):
  48.         #  we loop back on q to get the remainder of the remainders sum
  49.         previous, current = current, (previous + current) % q
  50.         pisano_period += 1
  51.     # we just need to find the remainder of p when divided by the Pisano period.
  52.     #  numbers are small enough now to use the naive approach
  53.     return get_fibonacci_huge_naive(p % pisano_period, q)
  54.  
  55.  
  56. # turns out that Sum(F(0->i)) = F(i+2) % 10 - 1
  57. def fib_sum_last_digit_faster(p):
  58.     res = get_fibonacci_huge_faster(p + 2, 10) - 1
  59.     # we loop back on 10 that is if the last digit is 0 we have reached a multiple of 10 and there for the last
  60.     # number is 9
  61.     if res == -1:
  62.         res = 9
  63.     return res
  64.  
  65.  
  66. # partial_sum(F(from), F(to)) = sum(F(to)) - sum(F(from - 1))
  67. def fibonacci_partial_sum_faster(p, q):
  68.     if p == q:
  69.         return get_fibonacci_huge_faster(p, 10)
  70.     elif p == 0:
  71.         return fib_sum_last_digit_faster(q)
  72.     res = fib_sum_last_digit_faster(q) - fib_sum_last_digit_faster(p - 1)
  73.     #  again we loop back on 10 if last digit of sum(F(p)) exceeds sum(F(q))
  74.     return res if res >= 0 else 10 + res
  75.  
  76. if __name__ == '__main__':
  77.     user_input = sys.stdin.read()
  78.     from_, to = map(int, user_input.split())
  79.     print(fibonacci_partial_sum_faster(from_, to))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement