import operator as op
import random
import sys


def memoize(f):
  cache = {}

  def helper(*args):
    if args not in cache:
      cache[args] = f(*args)
    return cache[args]

  return helper


def gcd(x, y):
  """
  Calculate greatest common divisor
  """
  while y != 0:
      t = x % y
      x, y = y, t
  return x


def gcd_multiple(*a):
  from six.moves import reduce
  """
  Apply gcd to some variables.
  Args: 
    a: args list
  """
  return reduce(gcd, a)


def egcd(a, b):
  """
  Calculate Extended-gcd
  """
  x, y, u, v = 0, 1, 1, 0
  while a != 0:
    q, r = b // a, b % a
    m, n = x - u * q, y - v * q
    b, a, x, y, u, v = a, r, u, v, m, n
  return (b, x, y)


def lcm(*a):
  from six.moves import reduce
  """
  Calculate Least Common Multiple
  Args:
    *a: args list
  """
  return reduce(op.mul, a) // gcd_multiple(*a)

def crt(ak, nk):
  from six.moves import reduce
  """
  Chinese-Reminders-Theorem Implementation
  using Gauss's proof and generalization on gcd(n1, n2) != 1
  Should be len(ak) == len(nk)
  Original: https://gist.github.com/elliptic-shiho/901d223135965308a5f9ff0cf99dd7c8
  Explanation: http://elliptic-shiho.hatenablog.com/entry/2016/04/03/020117

  Args:
    ak: A Numbers [a1, a2, ..., ak]
    nk: A Modulus [n1, n2, ..., nk]
  """
  assert len(ak) == len(nk)
  N = reduce(lambda x, y: x * y, nk, 1)
  l = lcm(*nk)
  s = 0
  for n, a in zip(nk, ak):
    m = N // n
    g, x, y = egcd(m, n)
    s += (m // g) * x * a
    s %= l
  return s


def legendre_symbol(a, p):
  """
  Calculate Legendre Symbol using Euler's criterion
  """
  if gcd(a, p) != 1:
    return 0
  d = pow(a, ((p - 1) // 2), p)
  if d == p - 1:
    return -1
  return 1


def jacobi_symbol(a, n):
  """
  Calculate Jacobi Symbol.
  """
  if is_prime(n):
    return legendre_symbol(a, n)
  j = 1
  while a != 0:
    while not a % 2:
      a //= 2
      if n & 7 == 3 or n & 7 == 5:
        j = -j
    a, n = n, a
    if a & 3 == 3 and n & 3 == 3:
      j = -j
    a %= n
  if n:
    return j
  return 0


def miller_rabin(x):
  from six.moves import xrange
  s = 0
  while (x - 1) % 2**(s + 1) == 0:
    s += 1
  d = x // (2**s)
  prime = 0
  for i in xrange(10):  # k = 10
    a = random.randint(1, x - 1)
    if not (pow(a, d, x) != 1 and all([pow(a, 2**r * d, x) != x - 1
            for r in xrange(0, s)])):
      prime += 1
  return prime > 6

def _check_external_modules():
  global _gmpy, _is_prime, _native, is_enable_native, _primefac
  try:
    import gmpy
    _gmpy = gmpy
    _is_prime = gmpy.is_prime
  except ImportError:
    _is_prime = miller_rabin
  try:
    import ecpy.native
    _native = ecpy.native
    is_enable_native = True
  except ImportError:
    _native = None
    is_enable_native = False
  try:
    import primefac
    _primefac = primefac
  except ImportError:
    _primefac = None


@memoize
def is_prime(x):
  """
  Is x prime?
  Args:
    x: Test Number (should be positive integer)
  """
  return _is_prime(x)


def modinv(a, m):
  """
  Calculate Modular Inverse.
  - Find x satisfy ax \equiv 1 \mod m

  Args:
    a: target number
    n: modulus
  """
  if gcd(a, m) != 1:
    return 0
  if a < 0:
    a %= m
  return egcd(a, m)[1] % m

@memoize
def prime_factorization(n):
  """
  Prime factorization of `n`
  Args:
    n: A integer
  Return: Factored `n`

  e.g. n = 2, return `{2: 1}`.
  """
  if is_prime(n):
    return {n: 1}
  if _primefac is not None:
    return _primefac.factorint(n)
  else:
    ret = {}
    # trial division method - too slow
    if n % 2 == 0:
      pow_2 = 0
      while n % 2 == 0:
        pow_2 += 1
        n //= 2
      ret[2] = pow_2
    while not is_prime(n):
      k = 3
      while n % k != 0:
        k += 2
      pow_k = 0
      while n % k == 0:
        pow_k += 1
        n //= k
      ret[k] = pow_k
    if n != 1:
      ret[n] = 1
    return ret


def euler_phi(n):
  '''
  Calculate Euler's totient function
  Args:
    n: A integer
  Return: Order of the group (Z/nZ)^*
  '''
  from ecpy.fields import QQ
  ret = 1
  factors = prime_factorization(n)
  for p in factors:
    k = factors[p]
    ret *= (1 - QQ(1, p))
  return int(ret * n)


_check_external_modules()