"""simple docstring"""



import itertools
import string
from collections.abc import Generator, Iterable





def 	_lowerCamelCase			(			UpperCAmelCase__,UpperCAmelCase__       )				->  List[str]:


   '''simple docstring'''


   a__  					=		iter(A__       )
   while True:
      a__  					=		tuple(itertools.islice(A__,A__       )       )
      if not chunk:
         return
      yield chunk





def 	_lowerCamelCase			(			UpperCAmelCase__       )				->  Dict:


   '''simple docstring'''


   a__  					=		"""""".join([c.upper() for c in dirty if c in string.ascii_letters]       )
   a__  					=		""""""

   if len(A__       ) < 2:
      return dirty

   for i in range(len(A__       ) - 1       ):
      clean += dirty[i]

      if dirty[i] == dirty[i + 1]:
         clean += "X"

   clean += dirty[-1]

   if len(A__       ) & 1:
      clean += "X"

   return clean





def 	_lowerCamelCase			(			UpperCAmelCase__       )				->  Any:


   '''simple docstring'''


   a__  					=		"""ABCDEFGHIKLMNOPQRSTUVWXYZ"""
   # we're using a list instead of a '2d' array because it makes the math
   # for setting up the table and doing the actual encoding/decoding simpler
   a__  					=		[]

   # copy key chars into the table if they are in `alphabet` ignoring duplicates
   for char in key.upper():
      if char not in table and char in alphabet:
         table.append(A__       )

      # fill the rest of the table in with the remaining alphabet chars
   for char in alphabet:
      if char not in table:
         table.append(A__       )

   return table





def 	_lowerCamelCase			(			UpperCAmelCase__,UpperCAmelCase__       )				->  Dict:


   '''simple docstring'''


   a__  					=		generate_table(A__       )
   a__  					=		prepare_input(A__       )
   a__  					=		""""""

   # https://en.wikipedia.org/wiki/Playfair_cipher#Description
   for chara, chara in chunker(A__,2       ):
      a__  					=		divmod(table.index(A__       ),5       )
      a__  					=		divmod(table.index(A__       ),5       )

      if rowa == rowa:
         ciphertext += table[rowa * 5 + (cola + 1) % 5]
         ciphertext += table[rowa * 5 + (cola + 1) % 5]
      elif cola == cola:
         ciphertext += table[((rowa + 1) % 5) * 5 + cola]
         ciphertext += table[((rowa + 1) % 5) * 5 + cola]
      else:  # rectangle
         ciphertext += table[rowa * 5 + cola]
         ciphertext += table[rowa * 5 + cola]

   return ciphertext





def 	_lowerCamelCase			(			UpperCAmelCase__,UpperCAmelCase__       )				->  Any:


   '''simple docstring'''


   a__  					=		generate_table(A__       )
   a__  					=		""""""

   # https://en.wikipedia.org/wiki/Playfair_cipher#Description
   for chara, chara in chunker(A__,2       ):
      a__  					=		divmod(table.index(A__       ),5       )
      a__  					=		divmod(table.index(A__       ),5       )

      if rowa == rowa:
         plaintext += table[rowa * 5 + (cola - 1) % 5]
         plaintext += table[rowa * 5 + (cola - 1) % 5]
      elif cola == cola:
         plaintext += table[((rowa - 1) % 5) * 5 + cola]
         plaintext += table[((rowa - 1) % 5) * 5 + cola]
      else:  # rectangle
         plaintext += table[rowa * 5 + cola]
         plaintext += table[rowa * 5 + cola]

   return plaintext






'''simple docstring'''






from math import factorial

__A   :    dict[str, int]											= {str(digit): factorial(digit) for digit in range(10)}







def 							UpperCamelCase_     (       A__   :  int   ):
  '''simple docstring'''





  if not isinstance(A__				,       A__   ):
    raise TypeError("""Parameter number must be int"""   )

  if number < 0:
    raise ValueError("""Parameter number must be greater than or equal to 0"""   )

  # Converts number in string to iterate on its digits and adds its factorial.
  return sum(DIGIT_FACTORIAL[digit] for digit in str(A__   )   )







def 							UpperCamelCase_     (       A__   :  int = 60				,       A__   :  int = 1_00_00_00   ):
  '''simple docstring'''





  if not isinstance(A__				,       A__   ) or not isinstance(A__				,       A__   ):
    raise TypeError("""Parameters chain_length and number_limit must be int"""   )

  if chain_length <= 0 or number_limit <= 0:
    raise ValueError(
        """Parameters chain_length and number_limit must be greater than 0"""   )

  # the counter for the chains with the exact desired length
  lowerCAmelCase_     : Optional[int]     =  0
  # the cached sizes of the previous chains
  lowerCAmelCase_     : dict[int, int]     =  {}

  for start_chain_element in range(1				,       A__   ):
    # The temporary set will contain the elements of the chain
    lowerCAmelCase_     : List[str]     =  set()
    lowerCAmelCase_     : Optional[int]     =  0

    # Stop computing the chain when you find a cached size, a repeating item or the
    # length is greater then the desired one.
    lowerCAmelCase_     : int     =  start_chain_element
    while (
        chain_element not in chain_sets_lengths
        and chain_element not in chain_set
        and chain_set_length <= chain_length
    ):
      chain_set.add(A__   )
      chain_set_length += 1
      lowerCAmelCase_     : Union[str, Any]     =  digit_factorial_sum(A__   )

    if chain_element in chain_sets_lengths:
      chain_set_length += chain_sets_lengths[chain_element]

    lowerCAmelCase_     : int     =  chain_set_length

    # If chain contains the exact amount of elements increase the counter
    if chain_set_length == chain_length:
      chains_counter += 1

  return chains_counter


if __name__ == "__main__":
  import doctest

  doctest.testmod()
  print(F'''{solution()}''')



