import timeit







class 			__snake_case   :
 def __init__(  self		,   snake_case__						)	->							int:
       '''simple docstring'''





       if isinstance(snake_case__		,   snake_case__						):  # Initializes a matrix identical to the one provided.
             UpperCAmelCase    : List[str]      =arg
             UpperCAmelCase    : List[str]      =len(snake_case__						)
       else:  # Initializes a square matrix of the given size and set values to zero.
             UpperCAmelCase    : List[str]      =arg
             UpperCAmelCase    : Tuple      =[[0 for _ in range(self.n						)] for _ in range(self.n						)]






 def __mul__(  self		,   snake_case__						)	->							Any:
       '''simple docstring'''





       UpperCAmelCase    : str      =Matrix(self.n						)
       for i in range(self.n						):
             for j in range(self.n						):
                   for k in range(self.n						):
                         matrix.t[i][j] += self.t[i][k] * b.t[k][j]
       return matrix





def   lowerCAmelCase_ (				__lowerCAmelCase		,					__lowerCAmelCase						)->  Optional[int]:






      '''simple docstring'''





      UpperCAmelCase    : Tuple      =Matrix([[1, 0], [0, 1]]						)
      while b > 0:
            if b & 1:
                  matrix *= a
            a *= a
            b >>= 1
      return matrix





def   lowerCAmelCase_ (				__lowerCAmelCase		,					__lowerCAmelCase		,					__lowerCAmelCase						)->  Any:






      '''simple docstring'''





      if n == 1:
            return fa
      elif n == 2:
            return fa
      UpperCAmelCase    : int      =Matrix([[1, 1], [1, 0]]						)
      UpperCAmelCase    : List[Any]      =modular_exponentiation(lowercase_		,					n - 2						)
      return fa * matrix.t[0][0] + fa * matrix.t[0][1]





def   lowerCAmelCase_ (				__lowerCAmelCase		,					__lowerCAmelCase		,					__lowerCAmelCase						)->  Optional[int]:






      '''simple docstring'''





      if n == 1:
            return fa
      elif n == 2:
            return fa

      UpperCAmelCase    : List[Any]      =fa
      UpperCAmelCase    : str      =fa
      n -= 2

      while n > 0:
            UpperCAmelCase    : Tuple      =fn_a + fn_a, fn_a
            n -= 1

      return fn_a





def   lowerCAmelCase_ (				)->  Tuple:






      '''simple docstring'''





      UpperCAmelCase    : str      ='\nfrom random import randint\nfrom __main__ import fibonacci_with_matrix_exponentiation\n'
      UpperCAmelCase    : Tuple      ='fibonacci_with_matrix_exponentiation(randint(1,70000), 1, 1)'
      UpperCAmelCase    : Tuple      =timeit.timeit(setup=lowercase_		,					stmt=lowercase_		,					number=1_00						)
      print('''With matrix exponentiation the average execution time is '''		,					exec_time / 1_00						)
      return exec_time





def   lowerCAmelCase_ (				)->  Any:






      '''simple docstring'''





      UpperCAmelCase    : Tuple      ='\nfrom random import randint\nfrom __main__ import simple_fibonacci\n'
      UpperCAmelCase    : Optional[Any]      ='simple_fibonacci(randint(1,70000), 1, 1)'
      UpperCAmelCase    : str      =timeit.timeit(setup=lowercase_		,					stmt=lowercase_		,					number=1_00						)
      print(
          '''Without matrix exponentiation the average execution time is '''		,					exec_time / 1_00						)
      return exec_time





def   lowerCAmelCase_ (				)->  int:






      '''simple docstring'''





      matrix_exponentiation_time()
      simple_fibonacci_time()


if __name__ == "__main__":
     main()

import math





def   lowerCAmelCase_ (				__lowerCAmelCase						)->  list[int]:






      '''simple docstring'''





      if not isinstance(__lowerCAmelCase		,					__lowerCAmelCase						):
            UpperCAmelCase    : Union[str, Any]      =f'''Input value of [number={number}] must be an integer'''
            raise TypeError(__lowerCAmelCase						)
      if number < 1:
            UpperCAmelCase    : Dict      =f'''Input value of [number={number}] must be a positive integer'''
            raise ValueError(__lowerCAmelCase						)
      UpperCAmelCase    : Dict      =[number]
      while number != 1:
            if number % 2 == 0:
                  UpperCAmelCase    : Optional[Any]      =math.floor(math.sqrt(__lowerCAmelCase						)						)
            else:
                  UpperCAmelCase    : List[str]      =math.floor(
                      math.sqrt(__lowerCAmelCase						) * math.sqrt(__lowerCAmelCase						) * math.sqrt(__lowerCAmelCase						)						)
            sequence.append(__lowerCAmelCase						)
      return sequence


if __name__ == "__main__":
     import doctest

     doctest.testmod()
