




import mpmath  # for roots of unity
import numpy as np




class 						__lowercase		:




      """simple docstring"""





      def __init__(				self    ,				A=None    ,				A=None     )		->    Union[str, Any]:
         # Input as list
         snake_case				:    Optional[int]           =	list(poly_a or [0]     )[:]
         snake_case				:    Dict           =	list(poly_b or [0]     )[:]

         # Remove leading zero coefficients
         while self.polyA[-1] == 0:
            self.polyA.pop()
         snake_case				:    Optional[Any]           =	len(self.polyA     )

         while self.polyB[-1] == 0:
            self.polyB.pop()
         snake_case				:    List[str]           =	len(self.polyB     )

         # Add 0 to make lengths equal a power of 2
         snake_case				:    str           =	int(
             2 ** np.ceil(np.loga(len(self.polyA     ) + len(self.polyB     ) - 1     )     )     )

         while len(self.polyA     ) < self.c_max_length:
            self.polyA.append(0     )
         while len(self.polyB     ) < self.c_max_length:
            self.polyB.append(0     )
         # A complex root used for the fourier transform
         snake_case				:    List[Any]           =	complex(mpmath.root(x=1    ,				n=self.c_max_length    ,				k=1     )     )

         # The product
         snake_case				:    Any           =	self.__multiply()




      def      UpperCAmelCase				(				self    ,				A     )		->    int:
         snake_case				:    List[str]           =	[[x] for x in self.polyA] if which == """A""" else [[x] for x in self.polyB]
         # Corner case
         if len(_lowerCAmelCase     ) <= 1:
            return dft[0]
         #
         snake_case				:    Any           =	self.c_max_length // 2
         while next_ncol > 0:
            snake_case				:    List[str]           =	[[] for i in range(_lowerCAmelCase     )]
            snake_case				:    Any           =	self.root**next_ncol

            # First half of next step
            snake_case				:    Optional[Any]           =	1
            for j in range(self.c_max_length // (next_ncol * 2)     ):
               for i in range(_lowerCAmelCase     ):
                  new_dft[i].append(dft[i][j] + current_root * dft[i + next_ncol][j]     )
               current_root *= root
            # Second half of next step
            snake_case				:    List[str]           =	1
            for j in range(self.c_max_length // (next_ncol * 2)     ):
               for i in range(_lowerCAmelCase     ):
                  new_dft[i].append(dft[i][j] - current_root * dft[i + next_ncol][j]     )
               current_root *= root
            # Update
            snake_case				:    List[Any]           =	new_dft
            snake_case				:    Union[str, Any]           =	next_ncol // 2
         return dft[0]




      def      UpperCAmelCase				(				self     )		->    List[Any]:
         snake_case				:    str           =	self.__dft("""A"""     )
         snake_case				:    Optional[int]           =	self.__dft("""B"""     )
         snake_case				:    Tuple           =	[[dft_a[i] * dft_b[i] for i in range(self.c_max_length     )]]
         del dft_a
         del dft_b

         # Corner Case
         if len(inverce_c[0]     ) <= 1:
            return inverce_c[0]
         # Inverse DFT
         snake_case				:    Tuple           =	2
         while next_ncol <= self.c_max_length:
            snake_case				:    Dict           =	[[] for i in range(_lowerCAmelCase     )]
            snake_case				:    Dict           =	self.root ** (next_ncol // 2)
            snake_case				:    Optional[Any]           =	1
            # First half of next step
            for j in range(self.c_max_length // next_ncol     ):
               for i in range(next_ncol // 2     ):
                  # Even positions
                  new_inverse_c[i].append(
                      (
                          inverce_c[i][j]
                          + inverce_c[i][j + self.c_max_length // next_ncol]
                      )
                      / 2     )
                  # Odd positions
                  new_inverse_c[i + next_ncol // 2].append(
                      (
                          inverce_c[i][j]
                          - inverce_c[i][j + self.c_max_length // next_ncol]
                      )
                      / (2 * current_root)     )
               current_root *= root
            # Update
            snake_case				:    Any           =	new_inverse_c
            next_ncol *= 2
         # Unpack
         snake_case				:    Any           =	[round(x[0].real    ,				8     ) + round(x[0].imag    ,				8     ) * 1j for x in inverce_c]

         # Remove leading 0's
         while inverce_c[-1] == 0:
            inverce_c.pop()
         return inverce_c




      def __str__(				self     )		->    Dict:
         snake_case				:    Any           =	"""A = """ + """ + """.join(
             f"""{coef}*x^{i}""" for coef, i in enumerate(self.polyA[: self.len_A]     )     )
         snake_case				:    Dict           =	"""B = """ + """ + """.join(
             f"""{coef}*x^{i}""" for coef, i in enumerate(self.polyB[: self.len_B]     )     )
         snake_case				:    Optional[Any]           =	"""A*B = """ + """ + """.join(
             f"""{coef}*x^{i}""" for coef, i in enumerate(self.product     )     )

         return f"""{a}\n{b}\n{c}"""


# Unit tests
if __name__ == "__main__":
       import doctest

       doctest.testmod()











import functools




def 						SCREAMING_SNAKE_CASE__ (   lowercase						,lowercase					)  ->       int:

   # Validation
   if not isinstance(lowercase						,lowercase					) or not all(isinstance(lowercase						,lowercase					) for day in days					):
      raise ValueError("""The parameter days should be a list of integers"""					)

   if len(lowercase					) != 3 or not all(isinstance(lowercase						,lowercase					) for cost in costs					):
      raise ValueError("""The parameter costs should be a list of three integers"""					)

   if len(lowercase					) == 0:
      return 0

   if min(lowercase					) <= 0:
      raise ValueError("""All days elements should be greater than 0"""					)

   if max(lowercase					) >= 366:
      raise ValueError("""All days elements should be less than 366"""					)

   snake_case				:    List[str]           =	set(lowercase					)

   @functools.cache
   def dynamic_programming(lowercase					) -> int:
      if index > 365:
         return 0

      if index not in days_set:
         return dynamic_programming(index + 1					)

      return min(
          costs[0] + dynamic_programming(index + 1					)						,costs[1] + dynamic_programming(index + 7					)						,costs[2] + dynamic_programming(index + 30					)						,)

   return dynamic_programming(1					)


if __name__ == "__main__":
       import doctest

       doctest.testmod()





