
'''simple docstring'''





class     _SCREAMING_SNAKE_CASE							:





				def __init__(		self :		Optional[Any]					,      snake_case_ :		List[str]							):


								"""simple docstring"""

								A     :  Tuple   =				val
								# Number of nodes in left subtree
								A     :  Dict   =				0
								A     :  int   =				None
								A     :  Dict   =				None
								A     :  Optional[Any]   =				None






				def        _UpperCAmelCase						(		self :		Dict					,      snake_case_ :		Optional[int]							):


								"""simple docstring"""

								assert self.left_tree_size == other.left_tree_size, "Unequal Sizes of Blocks"

								if self.val < other.val:
												A     :  Optional[Any]   =				self.right
												A     :  str   =				None
												if self.right:
																A     :  List[Any]   =				other
												A     :  List[Any]   =				other
												A     :  Any   =				self.left_tree_size * 2 + 1
												return self
								else:
												A     :  Tuple   =				other.right
												A     :  Union[str, Any]   =				None
												if other.right:
																A     :  List[Any]   =				self
												A     :  Any   =				self
												A     :  Optional[Any]   =				other.left_tree_size * 2 + 1
												return other



class     _SCREAMING_SNAKE_CASE							:





				def __init__(		self :		str					,      snake_case_ :		Union[str, Any]=None					,      snake_case_ :		List[Any]=None					,      snake_case_ :		Tuple=0							):


								"""simple docstring"""

								A     :  str   =				heap_size
								A     :  Dict   =				bottom_root
								A     :  Optional[int]   =				min_node





				def        _UpperCAmelCase						(		self :		str					,      snake_case_ :		Tuple							):


								"""simple docstring"""

								if other.size == 0:
												return None
								if self.size == 0:
												A     :  Tuple   =				other.size
												A     :  Optional[Any]   =				other.bottom_root
												A     :  List[Any]   =				other.min_node
												return None
								# Update size
								A     :  Tuple   =				self.size + other.size

								# Update min.node
								if self.min_node.val > other.min_node.val:
												A     :  Dict   =				other.min_node
								# Merge

								# Order roots by left_subtree_size
								A     :  List[Any]   =				[]
								A     :  str   =				self.bottom_root, other.bottom_root
								while i or j:
												if i and ((not j) or i.left_tree_size < j.left_tree_size):
																combined_roots_list.append((i, True)							)
																A     :  Union[str, Any]   =				i.parent
												else:
																combined_roots_list.append((j, False)							)
																A     :  Union[str, Any]   =				j.parent
        # Insert links between them
								for i in range(len(snake_case_							) - 1							):
												if combined_roots_list[i][1] != combined_roots_list[i + 1][1]:
																A     :  Dict   =				combined_roots_list[i + 1][0]
																A     :  Optional[Any]   =				combined_roots_list[i][0]
        # Consecutively merge roots with same left_tree_size
								A     :  Union[str, Any]   =				combined_roots_list[0][0]
								while i.parent:
												if (
												    (i.left_tree_size == i.parent.left_tree_size) and (not i.parent.parent)
												) or (
												    i.left_tree_size == i.parent.left_tree_size
												    and i.left_tree_size != i.parent.parent.left_tree_size
												):
																# Neighbouring Nodes
																A     :  Optional[int]   =				i.left
																A     :  Any   =				i.parent.parent

																# Merging trees
																A     :  List[Any]   =				i.merge_trees(i.parent							)

																# Updating links
																A     :  Tuple   =				previous_node
																A     :  Dict   =				next_node
																if previous_node:
																				A     :  Union[str, Any]   =				i
																if next_node:
																				A     :  Dict   =				i
												else:
																A     :  Optional[Any]   =				i.parent
        # Updating self.bottom_root
								while i.left:
												A     :  Dict   =				i.left
								A     :  int   =				i

								# Update other
								A     :  Any   =				self.size
								A     :  Optional[int]   =				self.bottom_root
								A     :  Tuple   =				self.min_node

								# Return the merged heap
								return self





				def        _UpperCAmelCase						(		self :		Any					,      snake_case_ :		Tuple							):


								"""simple docstring"""

								if self.size == 0:
												A     :  Tuple   =				Node(snake_case_							)
												A     :  int   =				1
												A     :  Any   =				self.bottom_root
								else:
												# Create new node
												A     :  Optional[int]   =				Node(snake_case_							)

												# Update size
												self.size += 1

												# update min_node
												if val < self.min_node.val:
																A     :  Tuple   =				new_node
												# Put new_node as a bottom_root in heap
												A     :  int   =				new_node
												A     :  Dict   =				self.bottom_root
												A     :  Any   =				new_node

												# Consecutively merge roots with same left_tree_size
												while (
												    self.bottom_root.parent
												    and self.bottom_root.left_tree_size
												    == self.bottom_root.parent.left_tree_size
												):
																# Next node
																A     :  Union[str, Any]   =				self.bottom_root.parent.parent

																# Merge
																A     :  List[Any]   =				self.bottom_root.merge_trees(self.bottom_root.parent							)

																# Update Links
																A     :  Union[str, Any]   =				next_node
																A     :  Optional[int]   =				None
																if next_node:
																				A     :  Optional[int]   =				self.bottom_root





				def        _UpperCAmelCase						(		self :		Dict							):


								"""simple docstring"""

								return self.min_node.val





				def        _UpperCAmelCase						(		self :		Optional[int]							):


								"""simple docstring"""

								return self.size == 0





				def        _UpperCAmelCase						(		self :		Tuple							):


								"""simple docstring"""

								A     :  Optional[int]   =				self.min_node.val

								# Last element in heap corner case
								if self.size == 1:
												# Update size
												A     :  Optional[int]   =				0

												# Update bottom root
												A     :  List[str]   =				None

												# Update min_node
												A     :  Dict   =				None

												return min_value
								# No right subtree corner case
								# The structure of the tree implies that this should be the bottom root
								# and there is at least one other root
								if self.min_node.right is None:
												# Update size
												self.size -= 1

												# Update bottom root
												A     :  Any   =				self.bottom_root.parent
												A     :  Union[str, Any]   =				None

												# Update min_node
												A     :  Optional[Any]   =				self.bottom_root
												A     :  Tuple   =				self.bottom_root.parent
												while i:
																if i.val < self.min_node.val:
																				A     :  List[Any]   =				i
																A     :  Optional[Any]   =				i.parent
												return min_value
								# General case
								# Find the BinomialHeap of the right subtree of min_node
								A     :  str   =				self.min_node.right
								A     :  Union[str, Any]   =				None
								A     :  Dict   =				bottom_of_new
								A     :  Tuple   =				1

								# Size, min_node and bottom_root
								while bottom_of_new.left:
												A     :  Any   =				size_of_new * 2 + 1
												A     :  str   =				bottom_of_new.left
												if bottom_of_new.val < min_of_new.val:
																A     :  str   =				bottom_of_new
        # Corner case of single root on top left path
								if (not self.min_node.left) and (not self.min_node.parent):
												A     :  Any   =				size_of_new
												A     :  Any   =				bottom_of_new
												A     :  List[Any]   =				min_of_new
												# print("Single root, multiple nodes case")
												return min_value
								# Remaining cases
								# Construct heap of right subtree
								A     :  Union[str, Any]   =				BinomialHeap(
								    bottom_root=snake_case_					,      min_node=snake_case_					,      heap_size=snake_case_							)

								# Update size
								A     :  List[str]   =				self.size - 1 - size_of_new

								# Neighbour nodes
								A     :  List[str]   =				self.min_node.left
								A     :  Union[str, Any]   =				self.min_node.parent

								# Initialize new bottom_root and min_node
								A     :  List[str]   =				previous_node or next_node
								A     :  List[str]   =				next_node

								# Update links of previous_node and search below for new min_node and
								# bottom_root
								if previous_node:
												A     :  List[str]   =				next_node

												# Update bottom_root and search for min_node below
												A     :  str   =				previous_node
												A     :  List[str]   =				previous_node
												while self.bottom_root.left:
																A     :  str   =				self.bottom_root.left
																if self.bottom_root.val < self.min_node.val:
																				A     :  List[str]   =				self.bottom_root
								if next_node:
												A     :  List[Any]   =				previous_node

												# Search for new min_node above min_node
												A     :  Optional[int]   =				next_node
												while i:
																if i.val < self.min_node.val:
																				A     :  Union[str, Any]   =				i
																A     :  Dict   =				i.parent
        # Merge heaps
								self.merge_heaps(snake_case_							)

								return min_value





				def        _UpperCAmelCase						(		self :		str							):


								"""simple docstring"""

								A     :  Dict   =				self.bottom_root
								while top_root.parent:
												A     :  List[str]   =				top_root.parent
								# preorder
								A     :  List[Any]   =				[]
								self.__traversal(snake_case_					,      snake_case_							)
								return heap_pre_order





				def        _UpperCAmelCase						(		self :		int					,      snake_case_ :		Dict					,      snake_case_ :		Dict					,      snake_case_ :		str=0							):


								"""simple docstring"""

								if curr_node:
												preorder.append((curr_node.val, level)							)
												self.__traversal(curr_node.left					,      snake_case_					,      level + 1							)
												self.__traversal(curr_node.right					,      snake_case_					,      level + 1							)
								else:
												preorder.append(('''#''', level)							)






				def __str__(		self :		Dict							):


								"""simple docstring"""

								if self.is_empty():
												return ""
								A     :  Dict   =				self.pre_order()

								return "\n".join(('''-''' * level + str(snake_case_							)) for value, level in preorder_heap							)


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

					doctest.testmod()

UpperCamelCase_  =	{
    "0": 1,
    "1": 1,
    "2": 2,
    "3": 6,
    "4": 24,
    "5": 1_20,
    "6": 7_20,
    "7": 50_40,
    "8": 4_03_20,
    "9": 36_28_80,
}

UpperCamelCase_  =	{1_45: 1_45}

UpperCamelCase_  =	{
    1_45: 0,
    1_69: 3,
    3_63_01: 3,
    14_54: 3,
    8_71: 2,
    4_53_61: 2,
    8_72: 2,
}





def 							_lowerCamelCase			(					lowerCamelCase_:  int		):



				'''simple docstring'''







				if n in CACHE_SUM_DIGIT_FACTORIALS:
								return CACHE_SUM_DIGIT_FACTORIALS[n]
				A     :  Tuple   =				sum(DIGIT_FACTORIALS[let] for let in str(lowerCamelCase_		)		)
				A     :  Dict   =				ret
				return ret





def 							_lowerCamelCase			(					lowerCamelCase_:  int				,	lowerCamelCase_:  set | None = None		):



				'''simple docstring'''







				A     :  Optional[int]   =				previous or set()
				if n in CHAIN_LENGTH_CACHE:
								return CHAIN_LENGTH_CACHE[n]
				A     :  Dict   =				sum_digit_factorials(lowerCamelCase_		)
				if next_number in previous:
								A     :  Optional[int]   =				0
								return 0
				else:
								previous.add(lowerCamelCase_		)
								A     :  str   =				1 + chain_length(lowerCamelCase_				,	lowerCamelCase_		)
								A     :  Any   =				ret
								return ret





def 							_lowerCamelCase			(					lowerCamelCase_:  int = 60				,	lowerCamelCase_:  int = 100_0000		):



				'''simple docstring'''







				return sum(1 for i in range(1				,	lowerCamelCase_		) if chain_length(lowerCamelCase_		) == num_terms		)


if __name__ == "__main__":
					print(F'''{solution() = }''')