結果

問題 No.2709 1975 Powers
ユーザー kemunikukemuniku
提出日時 2024-03-31 16:00:22
言語 Nim
(2.0.2)
結果
AC  
実行時間 1,763 ms / 2,000 ms
コード長 22,943 bytes
コンパイル時間 3,397 ms
コンパイル使用メモリ 78,672 KB
実行使用メモリ 6,548 KB
最終ジャッジ日時 2024-03-31 16:00:44
合計ジャッジ時間 21,896 ms
ジャッジサーバーID
(参考情報)
judge10 / judge13
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
6,548 KB
testcase_01 AC 1 ms
6,548 KB
testcase_02 AC 13 ms
6,548 KB
testcase_03 AC 891 ms
6,548 KB
testcase_04 AC 1,461 ms
6,548 KB
testcase_05 AC 1,000 ms
6,548 KB
testcase_06 AC 299 ms
6,548 KB
testcase_07 AC 2 ms
6,548 KB
testcase_08 AC 274 ms
6,548 KB
testcase_09 AC 996 ms
6,548 KB
testcase_10 AC 2 ms
6,548 KB
testcase_11 AC 26 ms
6,548 KB
testcase_12 AC 73 ms
6,548 KB
testcase_13 AC 1,043 ms
6,548 KB
testcase_14 AC 138 ms
6,548 KB
testcase_15 AC 160 ms
6,548 KB
testcase_16 AC 790 ms
6,548 KB
testcase_17 AC 4 ms
6,548 KB
testcase_18 AC 93 ms
6,548 KB
testcase_19 AC 1,433 ms
6,548 KB
testcase_20 AC 8 ms
6,548 KB
testcase_21 AC 264 ms
6,548 KB
testcase_22 AC 1,718 ms
6,548 KB
testcase_23 AC 1,693 ms
6,548 KB
testcase_24 AC 1,744 ms
6,548 KB
testcase_25 AC 1,763 ms
6,548 KB
testcase_26 AC 1,720 ms
6,548 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#{.checks:off.}
import macros;macro ImportExpand(s:untyped):untyped = parseStmt($s[2])
import macros
ImportExpand "cplib/tmpl/sheep.nim" <=== "when not declared CPLIB_TMPL_SHEEP:\n    const CPLIB_TMPL_SHEEP* = 1\n    {.warning[UnusedImport]: off.}\n    {.hint[XDeclaredButNotUsed]: off.}\n    import algorithm\n    import sequtils\n    import tables\n    import macros\n    import math\n    import sets\n    import strutils\n    import strformat\n    import sugar\n    import heapqueue\n    import streams\n    import deques\n    import bitops\n    import std/lenientops\n    import options\n    #入力系\n    proc scanf(formatstr: cstring){.header: \"<stdio.h>\", varargs.}\n    proc getchar(): char {.importc: \"getchar_unlocked\", header: \"<stdio.h>\", discardable.}\n    proc ii(): int {.inline.} = scanf(\"%lld\\n\", addr result)\n    proc lii(N: int): seq[int] {.inline.} = newSeqWith(N, ii())\n    proc si(): string {.inline.} =\n        result = \"\"\n        var c: char\n        while true:\n            c = getchar()\n            if c == ' ' or c == '\\n':\n                break\n            result &= c\n    #chmin,chmax\n    template `max=`(x, y) = x = max(x, y)\n    template `min=`(x, y) = x = min(x, y)\n    #bit演算\n    proc `%`(x: int, y: int): int = (((x mod y)+y) mod y)\n    proc `//`(x: int, y: int): int = (((x) - (x%y)) div (y))\n    proc `%=`(x: var int, y: int): void = x = x%y\n    proc `//=`(x: var int, y: int): void = x = x//y\n    proc `**`(x: int, y: int): int = x^y\n    proc `**=`(x: var int, y: int): void = x = x^y\n    proc `^`(x: int, y: int): int = x xor y\n    proc `|`(x: int, y: int): int = x or y\n    proc `&`(x: int, y: int): int = x and y\n    proc `>>`(x: int, y: int): int = x shr y\n    proc `<<`(x: int, y: int): int = x shl y\n    proc `~`(x: int): int = not x\n    proc `^=`(x: var int, y: int): void = x = x ^ y\n    proc `&=`(x: var int, y: int): void = x = x & y\n    proc `|=`(x: var int, y: int): void = x = x | y\n    proc `>>=`(x: var int, y: int): void = x = x >> y\n    proc `<<=`(x: var int, y: int): void = x = x << y\n    proc `[]`(x: int, n: int): bool = (x and (1 shl n)) != 0\n    #便利な変換\n    proc `!`(x: char, a = '0'): int = int(x)-int(a)\n    #定数\n    const INF = int(3300300300300300491)\n    #converter\n\n    #range\n    iterator range(start: int, ends: int, step: int): int =\n        var i = start\n        if step < 0:\n            while i > ends:\n                yield i\n                i += step\n        elif step > 0:\n            while i < ends:\n                yield i\n                i += step\n    iterator range(ends: int): int = (for i in 0..<ends: yield i)\n    iterator range(start: int, ends: int): int = (for i in\n            start..<ends: yield i)\n"
ImportExpand "cplib/math/powmod.nim" <=== "when not declared CPLIB_MATH_POWMOD:\n    const CPLIB_MATH_POWMOD* = 1\n    #[ import cplib/math/inner_math ]#\n    when not declared CPLIB_MATH_INNER_MATH:\n        const CPLIB_MATH_INNER_MATH* = 1\n        proc add*(a, b, m: int): int {.importcpp: \"((__int128)(#) + (__int128)(#)) % (__int128)(#)\", nodecl.}\n        proc mul*(a, b, m: int): int {.importcpp: \"(__int128)(#) * (__int128)(#) % (__int128)(#)\", nodecl.}\n    proc powmod*(a, n, m: int): int =\n        var\n            rev = 1\n            a = a\n            n = n\n        while n > 0:\n            if n mod 2 != 0: rev = mul(rev, a, m)\n            if n > 1: a = mul(a, a, m)\n            n = n shr 1\n        return rev\n"
ImportExpand "atcoder/modint.nim" <=== "when not declared ATCODER_MODINT_HPP:\n  const ATCODER_MODINT_HPP* = 1\n  import std/macros\n  #[ import atcoder/generate_definitions ]#\n  when not declared ATCODER_GENERATE_DEFINITIONS_NIM:\n    const ATCODER_GENERATE_DEFINITIONS_NIM* = 1\n    import std/macros\n  \n    type hasInv* = concept x\n      x.inv()\n  \n    template generateDefinitions*(name, l, r, typeObj, typeBase, body: untyped): untyped {.dirty.} =\n      proc name*(l, r: typeObj): auto {.inline.} =\n        type T = l.type\n        body\n      proc name*(l: typeBase; r: typeObj): auto {.inline.} =\n        type T = r.type\n        body\n      proc name*(l: typeObj; r: typeBase): auto {.inline.} =\n        type T = l.type\n        body\n  \n    template generatePow*(name) {.dirty.} =\n      proc pow*(m: name; p: SomeInteger): name {.inline.} =\n        when name is hasInv:\n          if p < 0: return pow(m.inv(), -p)\n        else:\n          doAssert p >= 0\n        if (p.type)(0) <= p:\n          var\n            p = p.uint\n            m = m\n          result = m.unit()\n          while p > 0'u:\n            if (p and 1'u) != 0'u: result *= m\n            m *= m\n            p = p shr 1'u\n      proc `^`*[T:name](m: T; p: SomeInteger): T {.inline.} = m.pow(p)\n  \n    macro generateConverter*(name, from_type, to_type) =\n      let fname = ident(\"to\" & $`name` & \"OfGenerateConverter\")\n      quote do:\n        type `name`* = `to_type`\n        converter `fname`*(a:`from_type`):`name` {.used.} =\n          `name`.init(a)\n    discard\n\n  type\n    StaticModInt*[M: static[int]] = object\n      a:uint32\n    DynamicModInt*[T: static[int]] = object\n      a:uint32\n\n  type ModInt* = StaticModInt or DynamicModInt\n#  type ModInt* = concept x, type T\n#    T is StaticModInt or T is DynamicModInt\n\n  proc isStaticModInt*(T:typedesc[ModInt]):bool = T is StaticModInt\n  proc isDynamicModInt*(T:typedesc[ModInt]):bool = T is DynamicModInt\n  #proc isModInt*(T:typedesc):bool = T.isStaticModInt or T.isDynamicModInt\n  proc isStatic*(T:typedesc[ModInt]):bool = T is StaticModInt\n  proc getMod*[M:static[int]](t:typedesc[StaticModInt[M]]):int {.inline.} = M\n\n\n  #[ import atcoder/internal_math ]#\n  when not declared ATCODER_INTERNAL_MATH_HPP:\n    const ATCODER_INTERNAL_MATH_HPP* = 1\n    import std/math\n  \n    # Fast moduler by barrett reduction\n    # Reference: https:#en.wikipedia.org/wiki/Barrett_reduction\n    # NOTE: reconsider after Ice Lake\n    type Barrett* = object\n      m*, im*:uint\n  \n    # @param m `1 <= m`\n    proc initBarrett*(m:uint):auto = Barrett(m:m, im:cast[uint](-1) div m + 1)\n  \n    # @return m\n    proc umod*(self: Barrett):uint =\n      self.m\n  \n    {.emit: \"\"\"\n  #include<cstdio>\n  inline unsigned long long calc_mul(const unsigned long long &a, const unsigned long long &b){\n    return (unsigned long long)(((unsigned __int128)(a)*b) >> 64);\n  }\n  \"\"\".}\n    proc calc_mul*(a,b:culonglong):culonglong {.importcpp: \"calc_mul(#,#)\", nodecl, inline.}\n    # @param a `0 <= a < m`\n    # @param b `0 <= b < m`\n    # @return `a * b % m`\n    proc quo*(self: Barrett, n:int | uint):int =\n      let n = n.uint\n      let x = calc_mul(n.culonglong, self.im.culonglong).uint\n      let r = n - x * self.m\n      return int(if self.m <= r: x - 1 else: x)\n    proc rem*(self: Barrett, n:int | uint):int =\n      let n = n.uint\n      let x = calc_mul(n.culonglong, self.im.culonglong).uint\n      let r = n - x * self.m\n      return int(if self.m <= r: r + self.m else: r)\n    proc quorem*(self: Barrett, n:int | uint):(int, int) =\n      let n = n.uint\n      let x = calc_mul(n.culonglong, self.im.culonglong).uint\n      let r = n - x * self.m\n      return if self.m <= r: (int(x - 1), int(r + self.m)) else: (int(x), int(r))\n  \n    proc pow*(self: Barrett, n:uint | int, p:int):int =\n      var\n        a = self.rem(n)\n        r:uint = if self.m == 1: 0 else: 1\n        p = p\n      while p > 0:\n        if (p and 1) != 0: r = self.mul(r, a.uint)\n        a = self.mul(a.uint, a.uint).int\n        p = p shr 1\n      return int(r)\n  \n    proc mul*(self: Barrett, a:uint, b:uint):uint {.inline.} =\n      # [1] m = 1\n      # a = b = im = 0, so okay\n  \n      # [2] m >= 2\n      # im = ceil(2^64 / m)\n      # -> im * m = 2^64 + r (0 <= r < m)\n      # let z = a*b = c*m + d (0 <= c, d < m)\n      # a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im\n      # c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2\n      # ((ab * im) >> 64) == c or c + 1\n      let z = a * b\n      #  #ifdef _MSC_VER\n      #      unsigned long long x;\n      #      _umul128(z, im, &x);\n      #  #else\n      ##TODO\n      #      unsigned long long x =\n      #        (unsigned long long)(((unsigned __int128)(z)*im) >> 64);\n      #  #endif\n      #let x = calc_mul(z.culonglong, self.im.culonglong).uint\n      #result = z - x * self.m\n      #if self.m <= result: result += self.m\n      return self.rem(z).uint\n  \n    # @param n `0 <= n`\n    # @param m `1 <= m`\n    # @return `(x ** n) % m`\n    proc pow_mod_constexpr*(x, n, m:int):int =\n      if m == 1: return 0\n      var\n        r = 1\n        y = floorMod(x, m)\n        n = n\n      while n != 0:\n        if (n and 1) != 0: r = (r * y) mod m\n        y = (y * y) mod m\n        n = n shr 1\n      return r.int\n    \n    # Reference:\n    # M. Forisek and J. Jancina,\n    # Fast Primality Testing for Integers That Fit into a Machine Word\n    # @param n `0 <= n`\n    proc is_prime_constexpr*(n:int):bool =\n      if n <= 1: return false\n      if n == 2 or n == 7 or n == 61: return true\n      if n mod 2 == 0: return false\n      var d = n - 1\n      while d mod 2 == 0: d = d div 2\n      for a in [2, 7, 61]:\n        var\n          t = d\n          y = pow_mod_constexpr(a, t, n)\n        while t != n - 1 and y != 1 and y != n - 1:\n          y = y * y mod n\n          t =  t shl 1\n        if y != n - 1 and t mod 2 == 0:\n          return false\n      return true\n    proc is_prime*[n:static[int]]():bool = is_prime_constexpr(n)\n  #  \n  #  # @param b `1 <= b`\n  #  # @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g\n    proc inv_gcd*(a, b:int):(int,int) =\n      var a = floorMod(a, b)\n      if a == 0: return (b, 0)\n    \n      # Contracts:\n      # [1] s - m0 * a = 0 (mod b)\n      # [2] t - m1 * a = 0 (mod b)\n      # [3] s * |m1| + t * |m0| <= b\n      var\n        s = b\n        t = a\n        m0 = 0\n        m1 = 1\n    \n      while t != 0:\n        var u = s div t\n        s -= t * u;\n        m0 -= m1 * u;  # |m1 * u| <= |m1| * s <= b\n    \n        # [3]:\n        # (s - t * u) * |m1| + t * |m0 - m1 * u|\n        # <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)\n        # = s * |m1| + t * |m0| <= b\n    \n        var tmp = s\n        s = t;t = tmp;\n        tmp = m0;m0 = m1;m1 = tmp;\n      # by [3]: |m0| <= b/g\n      # by g != b: |m0| < b/g\n      if m0 < 0: m0 += b div s\n      return (s, m0)\n  \n    # Compile time primitive root\n    # @param m must be prime\n    # @return primitive root (and minimum in now)\n    proc primitive_root_constexpr*(m:int):int =\n      if m == 2: return 1\n      if m == 167772161: return 3\n      if m == 469762049: return 3\n      if m == 754974721: return 11\n      if m == 998244353: return 3\n      var divs:array[20, int]\n      divs[0] = 2\n      var cnt = 1\n      var x = (m - 1) div 2\n      while x mod 2 == 0: x = x div 2\n      var i = 3\n      while i * i <= x:\n        if x mod i == 0:\n          divs[cnt] = i\n          cnt.inc\n          while x mod i == 0:\n            x = x div i\n        i += 2\n      if x > 1:\n        divs[cnt] = x\n        cnt.inc\n      var g = 2\n      while true:\n        var ok = true\n        for i in 0..<cnt:\n          if pow_mod_constexpr(g, (m - 1) div divs[i], m) == 1:\n            ok = false\n            break\n        if ok: return g\n        g.inc\n    proc primitive_root*[m:static[int]]():auto =\n      primitive_root_constexpr(m)\n  \n    # @param n `n < 2^32`\n    # @param m `1 <= m < 2^32`\n    # @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64)\n    proc floor_sum_unsigned*(n, m, a, b:uint):uint =\n      result = 0\n      var (n, m, a, b) = (n, m, a, b)\n      while true:\n        if a >= m:\n          result += n * (n - 1) div 2 * (a div m)\n          a = a mod m\n        if b >= m:\n          result += n * (b div m)\n          b = b mod m\n  \n        let y_max = a * n + b\n        if y_max < m: break\n        # y_max < m * (n + 1)\n        # floor(y_max / m) <= n\n        n = y_max div m\n        b = y_max mod m\n        swap(m, a)\n    discard\n\n  proc getBarrett*[T:static[int]](t:typedesc[DynamicModInt[T]]):ptr Barrett =\n    var Barrett_of_DynamicModInt {.global.} = initBarrett(998244353.uint)\n    return Barrett_of_DynamicModInt.addr\n  \n  proc getMod*[T:static[int]](t:typedesc[DynamicModInt[T]]):uint32 {.inline.} =\n    (t.getBarrett)[].m.uint32\n  proc setMod*[T:static[int]](t:typedesc[DynamicModInt[T]], M:SomeInteger){.inline.} =\n    (t.getBarrett)[] = initBarrett(M.uint)\n\n  proc val*(m: ModInt): int {.inline.} = int(m.a)\n\n  proc `$`*(m: StaticModInt or DynamicModInt): string {.inline.} = $(m.val())\n\n  template umod*[T:ModInt](self: typedesc[T] or T):uint32 =\n    when T is typedesc:\n      when T is StaticModInt:\n        T.M.uint32\n      elif T is DynamicModInt:\n        T.getMod()\n      else:\n        static: assert false\n    else: T.umod\n\n  template `mod`*[T:ModInt](self:typedesc[T] or T):int = T.umod.int\n\n  proc init*[T:ModInt](t:typedesc[T], v: SomeInteger or T): auto {.inline.} =\n    when v is T: return v\n    else:\n      when v is SomeUnsignedInt:\n        if v.uint < T.umod:\n          return T(a:v.uint32)\n        else:\n          return T(a:(v.uint mod T.umod.uint).uint32)\n      else:\n        var v = v.int\n        if 0 <= v:\n          if v < T.mod: return T(a:v.uint32)\n          else: return T(a:(v mod T.mod).uint32)\n        else:\n          v = v mod T.mod\n          if v < 0: v += T.mod\n          return T(a:v.uint32)\n  proc unit*[T:ModInt](t:typedesc[T] or T):T = T.init(1)\n\n  template initModInt*(v: SomeInteger or ModInt; M: static[int] = 1_000_000_007): auto =\n    StaticModInt[M].init(v)\n\n# TODO\n#  converter toModInt[M:static[int]](n:SomeInteger):StaticModInt[M] {.inline.} = initModInt(n, M)\n\n#  proc initModIntRaw*(v: SomeInteger; M: static[int] = 1_000_000_007): auto {.inline.} =\n#    ModInt[M](v.uint32)\n  proc raw*[T:ModInt](t:typedesc[T], v:SomeInteger):auto = T(a:v)\n\n  proc inv*[T:ModInt](v:T):T {.inline.} =\n    var\n      a = v.a.int\n      b = T.mod\n      u = 1\n      v = 0\n    while b > 0:\n      let t = a div b\n      a -= t * b;swap(a, b)\n      u -= t * v;swap(u, v)\n    return T.init(u)\n\n\n  proc `-`*[T:ModInt](m: T): T {.inline.} =\n    if int(m.a) == 0: return m\n    else: return T(a:m.umod() - m.a)\n\n  proc `+=`*[T:ModInt](m: var T; n: SomeInteger | T):T {.inline discardable.} =\n    m.a += T.init(n).a\n    if m.a >= T.umod: m.a -= T.umod\n    return m\n\n  proc `-=`*[T:ModInt](m: var T; n: SomeInteger | T):T {.inline discardable.} =\n    m.a -= T.init(n).a\n    if m.a >= T.umod: m.a += T.umod\n    return m\n\n  proc `*=`*[T:ModInt](m: var T; n: SomeInteger | T):T {.inline discardable.} =\n    when T is StaticModInt:\n      m.a = (m.a.uint * T.init(n).a.uint mod T.umod).uint32\n    elif T is DynamicModInt:\n      m.a = T.getBarrett[].mul(m.a.uint, T.init(n).a.uint).uint32\n    else:\n      static: assert false\n    return m\n\n  proc `/=`*[T:ModInt](m: var T; n: SomeInteger | T):T {.inline discardable.} =\n    m.a = (m.a.uint * T.init(n).inv().a.uint mod T.umod).uint32\n    return m\n\n  generateDefinitions(`+`, m, n, ModInt, SomeInteger):\n    result = T.init(m)\n    result += n\n\n  generateDefinitions(`-`, m, n, ModInt, SomeInteger):\n    result = T.init(m)\n    result -= n\n\n  generateDefinitions(`*`, m, n, ModInt, SomeInteger):\n    result = T.init(m)\n    result *= n\n\n  generateDefinitions(`/`, m, n, ModInt, SomeInteger):\n    result = T.init(m)\n    result /= n\n\n  generateDefinitions(`==`, m, n, ModInt, SomeInteger):\n    result = (T.init(m).val() == T.init(n).val())\n\n  proc inc*(m: var ModInt):ModInt {.inline discardable.} =\n    m.a.inc\n    if m.a == m.umod.uint32:\n      m.a = 0\n    return m\n  proc `++`*(m: var ModInt):ModInt {.inline discardable.} = m.inc\n\n  proc dec*(m: var ModInt):ModInt {.inline discardable.} =\n    if m.a == 0.uint32:\n      m.a = m.umod - 1\n    else:\n      m.a.dec\n    return m\n  proc `--`*(m: var ModInt):ModInt {.inline discardable.} = m.dec\n\n  generatePow(ModInt)\n  \n  # TODO: intのところはSomeIntegerに拡張したいがそうするとSystem.nimのuintのconverterとバッティングする。。。\n  template useStaticModint*(name, M) =\n    generateConverter(name, int, StaticModInt[M])\n  template useDynamicModInt*(name, M) =\n    generateConverter(name, int, DynamicModInt[M])\n\n  # TODO: Nimのstatic[int]を使うconverterがバグっていて個々に宣言しないとconverterが使えない\n  # したがって、下記以外のmodintを使う場合はuseStaticModIntあるいはuseDynamicModIntで宣言が必要\n  useStaticModInt(modint998244353, 998244353)\n  useStaticModInt(modint1000000007, 1000000007)\n  useDynamicModInt(modint, -1)\n\n  import std/math as math_lib_modint\n  proc estimateRational*(a:ModInt, ub:int = int(sqrt(float(ModInt.mod))), output_stderr:static[bool] = false):string =\n    var v:seq[tuple[s, n, d: int]]\n    for d in 1 .. ub:\n      var n = (a * d).val\n      # n or mod - n\n      if n * 2 > a.mod:\n        n = - (a.mod - n)\n      if gcd(n, d) > 1: continue\n      v.add((n.abs + d, n, d))\n    v.sort\n    when output_stderr:\n      stderr.write \"estimation result: \", v\n    return $v[0].n & \"/\" & $v[0].d\n\n  # TODO:\n  # Modint -> intのconverterあるとmint(2) * 3みたいなのがintになっちゃう\n  # converter toInt*(m: ModInt):int {.inline.} = m.val\n\n\n  discard\n"
# see https://github.com/zer0-star/Nim-ACL/tree/master/src/atcoder/mincostflow.nim
ImportExpand "atcoder/maxflow.nim" <=== "when not declared ATCODER_MAXFLOW_HPP:\n  const ATCODER_MAXFLOW_HPP* = 1\n  \n  #[ import atcoder/internal_queue ]#\n  when not declared ATCODER_INTERNAL_QUEUE_HPP:\n    const ATCODER_INTERNAL_QUEUE_HPP* = 1\n  \n    type simple_queue[T] = object\n      payload:seq[T]\n      pos:int\n    proc init_simple_queue*[T]():auto = simple_queue[T](payload:newSeq[T](), pos:0)\n  # TODO\n  #      void reserve(int n) { payload.reserve(n); }\n    proc len*[T](self:simple_queue[T]):int = self.payload.len - self.pos\n    proc empty*[T](self:simple_queue[T]):bool = self.pos == self.payload.len\n    proc push*[T](self:var simple_queue[T], t:T) = self.payload.add(t)\n    proc front*[T](self:simple_queue[T]):T = self.payload[self.pos]\n    proc clear*[T](self:var simple_queue[T]) =\n      self.payload.setLen(0)\n      self.pos = 0;\n    proc pop*[T](self:var simple_queue[T]) = self.pos.inc\n    discard\n  import std/algorithm\n\n  type MFInternalEdge[Cap] = object\n    dst, rev:int\n    cap:Cap\n  \n  type MFGraph*[Cap] = object\n    len*:int\n    pos:seq[(int,int)]\n    g:seq[seq[MFInternalEdge[Cap]]]\n  \n  proc init_mf_graph*[Cap](n:int):auto = MFGraph[Cap](len:n, g:newSeq[seq[MFInternalEdge[Cap]]](n))\n  proc initMaxFlow*[Cap](n:int):auto = MFGraph[Cap](len:n, g:newSeq[seq[MFInternalEdge[Cap]]](n))\n  \n  proc add_edge*[Cap](self: var MFGraph[Cap], src, dst:int, cap:Cap):int {.discardable.}=\n    assert src in 0..<self.len\n    assert dst in 0..<self.len\n    assert 0.Cap <= cap\n    let m = self.pos.len\n    self.pos.add((src, self.g[src].len))\n    var src_id = self.g[src].len\n    var dst_id = self.g[dst].len\n    if src == dst: dst_id.inc\n    self.g[src].add(MFInternalEdge[Cap](dst:dst, rev:dst_id, cap:cap))\n    self.g[dst].add(MFInternalEdge[Cap](dst:src, rev:src_id, cap:0))\n    return m\n  \n  type MFEdge*[Cap] = object\n    src*, dst*:int\n    cap*, flow*:Cap\n  \n  proc get_edge*[Cap](self: MFGraph[Cap], i:int):MFEdge[Cap] =\n    let m = self.pos.len\n    assert i in 0..<m\n    let e = self.g[self.pos[i][0]][self.pos[i][1]]\n    let re = self.g[e.dst][e.rev]\n    return MFEdge[Cap](src:self.pos[i][0], dst:e.dst, cap:e.cap + re.cap, flow:re.cap)\n\n  proc edges*[Cap](self: MFGraph[Cap]):seq[MFEdge[Cap]] =\n    let m = self.pos.len\n    result = newSeqOfCap[MFEdge[Cap]](m)\n    for i in 0..<m:\n      result.add(self.get_edge(i))\n\n  proc change_edge*[Cap](self: var MFGraph[Cap], i:int, new_cap, new_flow:Cap) =\n    let m = self.pos.len\n    assert i in 0..<m\n    assert new_flow in 0..new_cap\n    var e = self.g[self.pos[i][0]][self.pos[i][1]].addr\n    var re = self.g[e[].dst][e[].rev].addr\n    e[].cap = new_cap - new_flow\n    re[].cap = new_flow\n\n  proc flow*[Cap](self: var MFGraph[Cap], s, t:int, flow_limit:Cap):Cap =\n    assert s in 0..<self.len\n    assert t in 0..<self.len\n    assert s != t\n  \n    var level, iter = newSeq[int](self.len)\n    var que = init_simple_queue[int]()\n#    internal::simple_queue<int> que;\n  \n    proc bfs(self: MFGraph[Cap]) =\n      level.fill(-1)\n      level[s] = 0\n      que.clear()\n      que.push(s)\n      while not que.empty():\n        let v = que.front()\n        que.pop()\n        for e in self.g[v]:\n          if e.cap == 0 or level[e.dst] >= 0: continue\n          level[e.dst] = level[v] + 1\n          if e.dst == t: return\n          que.push(e.dst)\n    proc dfs(self: var MFGraph[Cap], v:int, up:Cap):Cap =\n      if v == s: return up\n      result = Cap(0)\n      let level_v = level[v]\n      var i = iter[v].addr\n      while i[] < self.g[v].len:\n        let e = self.g[v][i[]].addr\n        if level_v <= level[e[].dst] or self.g[e[].dst][e[].rev].cap == 0:\n          i[].inc\n          continue\n        let d = self.dfs(e.dst, min(up - result, self.g[e[].dst][e[].rev].cap))\n        if d <= 0:\n          i[].inc\n          continue\n        self.g[v][i[]].cap += d\n        self.g[e[].dst][e[].rev].cap -= d\n        result += d\n        if result == up: return\n        i[].inc\n      level[v] = self.len\n\n    var flow = Cap(0)\n    while flow < flow_limit:\n      self.bfs()\n      if level[t] == -1: break\n      iter.fill(0)\n      let f = self.dfs(t, flow_limit - flow)\n      if f == Cap(0): break\n      flow += f\n    return flow\n\n  proc flow*[Cap](self: var MFGraph[Cap], s,t:int):auto = self.flow(s, t, Cap.high)\n\n  proc min_cut*[Cap](self:MFGraph[Cap], s:int):seq[bool] =\n    var visited = newSeq[bool](self.len)\n    var que = init_simple_queue[int]()\n    que.push(s)\n    while not que.empty():\n      let p = que.front()\n      que.pop()\n      visited[p] = true\n      for e in self.g[p]:\n        if e.cap != Cap(0) and not visited[e.dst]:\n          visited[e.dst] = true\n          que.push(e.dst)\n    return visited\n  discard\n"

var N,P,Q = ii()
var A = lii(N)
A.sort()
var I = A.mapit(powmod(10,it,P))
var J = A.mapit(powmod(9,it,P))
var K = A.mapit(powmod(7,it,P))
var L = A.mapit(powmod(5,it,P))
var ans = 0
for a in range(N):
    for b in range(a+1,N):
        for c in range(b+1,N):
            for d in range(c+1,N):
                if (I[a]+J[b]+K[c]+L[d])%P == Q:
                    ans += 1
echo ans
0