結果

問題 No.2892 Lime and Karin
ユーザー 👑 seekworserseekworser
提出日時 2024-07-05 11:16:10
言語 Nim
(2.0.2)
結果
AC  
実行時間 5,892 ms / 8,000 ms
コード長 42,669 bytes
コンパイル時間 8,181 ms
コンパイル使用メモリ 116,736 KB
実行使用メモリ 39,040 KB
最終ジャッジ日時 2024-07-05 12:29:27
合計ジャッジ時間 93,168 ms
ジャッジサーバーID
(参考情報)
judge5 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
5,248 KB
testcase_01 AC 2 ms
5,248 KB
testcase_02 AC 2 ms
5,376 KB
testcase_03 AC 2 ms
5,376 KB
testcase_04 AC 2 ms
5,376 KB
testcase_05 AC 2 ms
5,376 KB
testcase_06 AC 2 ms
5,376 KB
testcase_07 AC 2 ms
5,376 KB
testcase_08 AC 2 ms
5,376 KB
testcase_09 AC 2 ms
5,376 KB
testcase_10 AC 2 ms
5,376 KB
testcase_11 AC 2 ms
5,376 KB
testcase_12 AC 2 ms
5,376 KB
testcase_13 AC 2 ms
5,376 KB
testcase_14 AC 1,284 ms
15,232 KB
testcase_15 AC 1,308 ms
13,696 KB
testcase_16 AC 2,386 ms
19,840 KB
testcase_17 AC 435 ms
7,936 KB
testcase_18 AC 2,068 ms
19,712 KB
testcase_19 AC 2,944 ms
25,472 KB
testcase_20 AC 121 ms
5,376 KB
testcase_21 AC 1,500 ms
16,512 KB
testcase_22 AC 2,065 ms
20,864 KB
testcase_23 AC 728 ms
10,624 KB
testcase_24 AC 3,101 ms
26,240 KB
testcase_25 AC 2,886 ms
26,752 KB
testcase_26 AC 2,898 ms
26,624 KB
testcase_27 AC 2,907 ms
27,136 KB
testcase_28 AC 3,128 ms
26,368 KB
testcase_29 AC 2,894 ms
26,496 KB
testcase_30 AC 2,828 ms
24,832 KB
testcase_31 AC 2,555 ms
26,880 KB
testcase_32 AC 2,634 ms
27,264 KB
testcase_33 AC 2,687 ms
26,368 KB
testcase_34 AC 478 ms
33,024 KB
testcase_35 AC 488 ms
32,768 KB
testcase_36 AC 486 ms
33,152 KB
testcase_37 AC 482 ms
33,024 KB
testcase_38 AC 487 ms
33,152 KB
testcase_39 AC 5,892 ms
39,040 KB
testcase_40 AC 2,934 ms
34,944 KB
testcase_41 AC 2,923 ms
31,104 KB
testcase_42 AC 2,893 ms
35,456 KB
testcase_43 AC 2,909 ms
32,512 KB
testcase_44 AC 1,060 ms
12,544 KB
testcase_45 AC 2,535 ms
22,784 KB
testcase_46 AC 1,228 ms
13,952 KB
testcase_47 AC 1,423 ms
17,408 KB
testcase_48 AC 582 ms
9,472 KB
testcase_49 AC 1,637 ms
19,584 KB
testcase_50 AC 1,667 ms
28,032 KB
testcase_51 AC 1,596 ms
28,032 KB
testcase_52 AC 1,536 ms
28,032 KB
testcase_53 AC 1,572 ms
28,032 KB
testcase_54 AC 1,649 ms
27,904 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

import macros;macro ImportExpand(s:untyped):untyped = parseStmt($s[2])
# source: https://github.com/kemuniku/cplib/tree/main/src/cplib/tmpl/citrus.nim
ImportExpand "cplib/tmpl/citrus" <=== "when not declared CPLIB_TMPL_CITRUS:\n    const CPLIB_TMPL_CITRUS* = 1\n    {.warning[UnusedImport]: off.}\n    {.hint[XDeclaredButNotUsed]: off.}\n    import os\n    import algorithm\n    import sequtils\n    import tables\n    import macros\n    import std/math\n    import sets\n    import strutils\n    import strformat\n    import sugar\n    import streams\n    import deques\n    import bitops\n    import heapqueue\n    import options\n    import hashes\n    const MODINT998244353* = 998244353\n    const MODINT1000000007* = 1000000007\n    when not declared CPLIB_UTILS_CONSTANTS:\n        const CPLIB_UTILS_CONSTANTS* = 1\n        const INF32*: int32 = 100100111.int32\n        const INF64*: int = int(3300300300300300491)\n    \n    const INFL = INF64\n    type double* = float64\n    let readNext = iterator(getsChar: bool = false): string {.closure.} =\n        while true:\n            var si: string\n            try: si = stdin.readLine\n            except EOFError: yield \"\"\n            for s in si.split:\n                if getsChar:\n                    for i in 0..<s.len():\n                        yield s[i..i]\n                else:\n                    if s.isEmptyOrWhitespace: continue\n                    yield s\n    proc input*(t: typedesc[string]): string = readNext()\n    proc input*(t: typedesc[char]): char = readNext(true)[0]\n    proc input*(t: typedesc[int]): int = readNext().parseInt\n    proc input*(t: typedesc[float]): float = readNext().parseFloat\n    macro input*(t: typedesc, n: varargs[int]): untyped =\n        var repStr = \"\"\n        for arg in n:\n            repStr &= &\"({arg.repr}).newSeqWith \"\n        parseExpr(&\"{repStr}input({t})\")\n    macro input*(ts: varargs[auto]): untyped =\n        var tupStr = \"\"\n        for t in ts:\n            tupStr &= &\"input({t.repr}),\"\n        parseExpr(&\"({tupStr})\")\n    macro input*(n: int, ts: varargs[auto]): untyped =\n        for typ in ts:\n            if typ.typeKind != ntyAnything:\n                error(\"Expected typedesc, got \" & typ.repr, typ)\n        parseExpr(&\"({n.repr}).newSeqWith input({ts.repr})\")\n    proc `fmtprint`*(x: int or string or char or bool): string = return $x\n    proc `fmtprint`*(x: float or float32 or float64): string = return &\"{x:.16f}\"\n    proc `fmtprint`*[T](x: seq[T] or Deque[T] or HashSet[T] or set[T]): string = return x.toSeq.join(\" \")\n    proc `fmtprint`*[T, N](x: array[T, N]): string = return x.toSeq.join(\" \")\n    proc `fmtprint`*[T](x: HeapQueue[T]): string =\n        var q = x\n        while q.len != 0:\n            result &= &\"{q.pop()}\"\n            if q.len != 0: result &= \" \"\n    proc `fmtprint`*[T](x: CountTable[T]): string =\n        result = x.pairs.toSeq.mapIt(&\"{it[0]}: {it[1]}\").join(\" \")\n    proc `fmtprint`*[K, V](x: Table[K, V]): string =\n        result = x.pairs.toSeq.mapIt(&\"{it[0]}: {it[1]}\").join(\" \")\n    proc print*(prop: tuple[f: File, sepc: string, endc: string, flush: bool], args: varargs[string, `fmtprint`]) =\n        for i in 0..<len(args):\n            prop.f.write(&\"{args[i]}\")\n            if i != len(args) - 1: prop.f.write(prop.sepc) else: prop.f.write(prop.endc)\n        if prop.flush: prop.f.flushFile()\n    proc print*(args: varargs[string, `fmtprint`]) = print((f: stdout, sepc: \" \", endc: \"\\n\", flush: false), args)\n    const LOCAL_DEBUG{.booldefine.} = false\n    macro getSymbolName(x: typed): string = x.toStrLit\n    macro debug*(args: varargs[untyped]): untyped =\n        when LOCAL_DEBUG:\n            result = newNimNode(nnkStmtList, args)\n            template prop(e: string = \"\"): untyped = (f: stderr, sepc: \"\", endc: e, flush: true)\n            for i, arg in args:\n                if arg.kind == nnkStrLit:\n                    result.add(quote do: print(prop(), \"\\\"\", `arg`, \"\\\"\"))\n                else:\n                    result.add(quote do: print(prop(\": \"), getSymbolName(`arg`)))\n                    result.add(quote do: print(prop(), `arg`))\n                if i != args.len - 1: result.add(quote do: print(prop(), \", \"))\n                else: result.add(quote do: print(prop(), \"\\n\"))\n        else:\n            return (quote do: discard)\n    proc `%`*(x: SomeInteger, y: SomeInteger): int =\n        result = x mod y\n        if y > 0 and result < 0: result += y\n        if y < 0 and result > 0: result += y\n    proc `//`*(x: SomeInteger, y: SomeInteger): int =\n        result = x div y\n        if y > 0 and result * y > x: result -= 1\n        if y < 0 and result * y < x: result -= 1\n    proc `^`*(x: SomeInteger, y: SomeInteger): int = x xor y\n    proc `&`*(x: SomeInteger, y: SomeInteger): int = x and y\n    proc `|`*(x: SomeInteger, y: SomeInteger): int = x or y\n    proc `>>`*(x: SomeInteger, y: SomeInteger): int = x shr y\n    proc `<<`*(x: SomeInteger, y: SomeInteger): int = x shl y\n    proc `%=`*(x: var SomeInteger, y: SomeInteger): void = x = x % y\n    proc `//=`*(x: var SomeInteger, y: SomeInteger): void = x = x // y\n    proc `^=`*(x: var SomeInteger, y: SomeInteger): void = x = x ^ y\n    proc `&=`*(x: var SomeInteger, y: SomeInteger): void = x = x & y\n    proc `|=`*(x: var SomeInteger, y: SomeInteger): void = x = x | y\n    proc `>>=`*(x: var SomeInteger, y: SomeInteger): void = x = x >> y\n    proc `<<=`*(x: var SomeInteger, y: SomeInteger): void = x = x << y\n    proc `[]`*(x, n: int): bool = (x and (1 shl n)) != 0\n    proc `[]=`*(x: var int, n: int, i: bool) =\n        if i: x = x or (1 << n)\n        else: (if x[n]: x = x xor (1 << n))\n    proc pow*(a, n: int, m = INF64): int =\n        var\n            rev = 1\n            a = a\n            n = n\n        while n > 0:\n            if n % 2 != 0: rev = (rev * a) mod m\n            if n > 1: a = (a * a) mod m\n            n >>= 1\n        return rev\n    when not declared CPLIB_MATH_ISQRT:\n        const CPLIB_MATH_ISQRT* = 1\n        proc isqrt*(n: int): int =\n            var x = n\n            var y = (x + 1) shr 1\n            while y < x:\n                x = y\n                y = (x + n div x) shr 1\n            return x\n    \n    proc chmax*[T](x: var T, y: T): bool {.discardable.} = (if x < y: (x = y; return true; ) return false)\n    proc chmin*[T](x: var T, y: T): bool {.discardable.} = (if x > y: (x = y; return true; ) return false)\n    proc `max=`*[T](x: var T, y: T) = x = max(x, y)\n    proc `min=`*[T](x: var T, y: T) = x = min(x, y)\n    proc at*(x: char, a = '0'): int = int(x) - int(a)\n    proc Yes*(b: bool = true): void = print(if b: \"Yes\" else: \"No\")\n    proc No*(b: bool = true): void = Yes(not b)\n    proc YES_upper*(b: bool = true): void = print(if b: \"YES\" else: \"NO\")\n    proc NO_upper*(b: bool = true): void = Yes_upper(not b)\n    const DXY* = [(0, -1), (0, 1), (-1, 0), (1, 0)]\n    const DDXY* = [(1, -1), (1, 0), (1, 1), (0, -1), (0, 1), (-1, -1), (-1, 0), (-1, 1)]\n    macro exit*(statement: untyped): untyped = (quote do: (`statement`; quit()))\n    proc initHashSet[T](): Hashset[T] = initHashSet[T](0)\n"
# source: https://github.com/kemuniku/cplib/tree/main/src/cplib/graph/graph.nim
ImportExpand "cplib/graph/graph" <=== "when not declared CPLIB_GRAPH_GRAPH:\n    const CPLIB_GRAPH_GRAPH* = 1\n\n    import sequtils\n    import math\n    type DynamicGraph*[T] = ref object of RootObj\n        edges*: seq[seq[(int32, T)]]\n        len*: int\n    type StaticGraph*[T] = ref object of RootObj\n        src*, dst*: seq[int32]\n        cost*: seq[T]\n        elist*: seq[(int32, T)]\n        start*: seq[int32]\n        len*: int\n\n    type WeightedDirectedGraph*[T] = ref object of DynamicGraph[T]\n    type WeightedUnDirectedGraph*[T] = ref object of DynamicGraph[T]\n    type UnWeightedDirectedGraph* = ref object of DynamicGraph[int]\n    type UnWeightedUnDirectedGraph* = ref object of DynamicGraph[int]\n    type WeightedDirectedStaticGraph*[T] = ref object of StaticGraph[T]\n    type WeightedUnDirectedStaticGraph*[T] = ref object of StaticGraph[T]\n    type UnWeightedDirectedStaticGraph* = ref object of StaticGraph[int]\n    type UnWeightedUnDirectedStaticGraph* = ref object of StaticGraph[int]\n\n    type GraphTypes*[T] = DynamicGraph[T] or StaticGraph[T]\n    type DirectedGraph* = WeightedDirectedGraph or UnWeightedDirectedGraph or WeightedDirectedStaticGraph or UnWeightedDirectedStaticGraph\n    type UnDirectedGraph* = WeightedUnDirectedGraph or UnWeightedUnDirectedGraph or WeightedUnDirectedStaticGraph or UnWeightedUnDirectedStaticGraph\n    type WeightedGraph*[T] = WeightedDirectedGraph[T] or WeightedUnDirectedGraph[T] or WeightedDirectedStaticGraph[T] or WeightedUnDirectedStaticGraph[T]\n    type UnWeightedGraph* = UnWeightedDirectedGraph or UnWeightedUnDirectedGraph or UnWeightedDirectedStaticGraph or UnWeightedUnDirectedStaticGraph\n    type DynamicGraphTypes* = WeightedDirectedGraph or UnWeightedDirectedGraph or WeightedUnDirectedGraph or UnWeightedUnDirectedGraph\n    type StaticGraphTypes* = WeightedDirectedStaticGraph or UnWeightedDirectedStaticGraph or WeightedUnDirectedStaticGraph or UnWeightedUnDirectedStaticGraph\n\n    proc add_edge_dynamic_impl*[T](g: DynamicGraph[T], u, v: int, cost: T, directed: bool) =\n        g.edges[u].add((v.int32, cost))\n        if not directed: g.edges[v].add((u.int32, cost))\n\n    proc initWeightedDirectedGraph*(N: int, edgetype: typedesc = int): WeightedDirectedGraph[edgetype] =\n        result = WeightedDirectedGraph[edgetype](edges: newSeq[seq[(int32, edgetype)]](N), len: N)\n    proc add_edge*[T](g: var WeightedDirectedGraph[T], u, v: int, cost: T) =\n        g.add_edge_dynamic_impl(u, v, cost, true)\n\n    proc initWeightedUnDirectedGraph*(N: int, edgetype: typedesc = int): WeightedUnDirectedGraph[edgetype] =\n        result = WeightedUnDirectedGraph[edgetype](edges: newSeq[seq[(int32, edgetype)]](N), len: N)\n    proc add_edge*[T](g: var WeightedUnDirectedGraph[T], u, v: int, cost: T) =\n        g.add_edge_dynamic_impl(u, v, cost, false)\n\n    proc initUnWeightedDirectedGraph*(N: int): UnWeightedDirectedGraph =\n        result = UnWeightedDirectedGraph(edges: newSeq[seq[(int32, int)]](N), len: N)\n    proc add_edge*(g: var UnWeightedDirectedGraph, u, v: int) =\n        g.add_edge_dynamic_impl(u, v, 1, true)\n\n    proc initUnWeightedUnDirectedGraph*(N: int): UnWeightedUnDirectedGraph =\n        result = UnWeightedUnDirectedGraph(edges: newSeq[seq[(int32, int)]](N), len: N)\n    proc add_edge*(g: var UnWeightedUnDirectedGraph, u, v: int) =\n        g.add_edge_dynamic_impl(u, v, 1, false)\n\n    proc len*[T](G: WeightedGraph[T]): int = G.len\n    proc len*(G: UnWeightedGraph): int = G.len\n\n    iterator `[]`*[T](g: WeightedDirectedGraph[T] or WeightedUnDirectedGraph[T], x: int): (int, T) =\n        for e in g.edges[x]: yield (e[0].int, e[1])\n    iterator `[]`*(g: UnWeightedDirectedGraph or UnWeightedUnDirectedGraph, x: int): int =\n        for e in g.edges[x]: yield e[0].int\n\n    proc add_edge_static_impl*[T](g: StaticGraph[T], u, v: int, cost: T, directed: bool) =\n        g.src.add(u.int32)\n        g.dst.add(v.int32)\n        g.cost.add(cost)\n        if not directed:\n            g.src.add(v.int32)\n            g.dst.add(u.int32)\n            g.cost.add(cost)\n\n    proc build_impl*[T](g: StaticGraph[T]) =\n        g.start = newSeqWith(g.len + 1, 0.int32)\n        for i in 0..<g.src.len:\n            g.start[g.src[i]] += 1\n        g.start.cumsum\n        g.elist = newSeq[(int32, T)](g.start[^1])\n        for i in countdown(g.src.len - 1, 0):\n            var u = g.src[i]\n            var v = g.dst[i]\n            g.start[u] -= 1\n            g.elist[g.start[u]] = (v, g.cost[i])\n    proc build*(g: StaticGraphTypes) = g.build_impl()\n\n    proc initWeightedDirectedStaticGraph*(N: int, edgetype: typedesc = int, capacity: int = 0): WeightedDirectedStaticGraph[edgetype] =\n        result = WeightedDirectedStaticGraph[edgetype](\n            src: newSeqOfCap[int32](capacity),\n            dst: newSeqOfCap[int32](capacity),\n            cost: newSeqOfCap[edgetype](capacity),\n            elist: newSeq[(int32, edgetype)](0),\n            start: newSeq[int32](0),\n            len: N\n        )\n    proc add_edge*[T](g: var WeightedDirectedStaticGraph[T], u, v: int, cost: T) =\n        g.add_edge_static_impl(u, v, cost, true)\n\n    proc initWeightedUnDirectedStaticGraph*(N: int, edgetype: typedesc = int, capacity: int = 0): WeightedUnDirectedStaticGraph[edgetype] =\n        result = WeightedUnDirectedStaticGraph[edgetype](\n            src: newSeqOfCap[int32](capacity*2),\n            dst: newSeqOfCap[int32](capacity*2),\n            cost: newSeqOfCap[edgetype](capacity*2),\n            elist: newSeq[(int32, edgetype)](0),\n            start: newSeq[int32](0),\n            len: N\n        )\n    proc add_edge*[T](g: var WeightedUnDirectedStaticGraph[T], u, v: int, cost: T) =\n        g.add_edge_static_impl(u, v, cost, false)\n\n    proc initUnWeightedDirectedStaticGraph*(N: int, capacity: int = 0): UnWeightedDirectedStaticGraph =\n        result = UnWeightedDirectedStaticGraph(\n            src: newSeqOfCap[int32](capacity),\n            dst: newSeqOfCap[int32](capacity),\n            cost: newSeqOfCap[int](capacity),\n            elist: newSeq[(int32, int)](0),\n            start: newSeq[int32](0),\n            len: N\n        )\n    proc add_edge*(g: var UnWeightedDirectedStaticGraph, u, v: int) =\n        g.add_edge_static_impl(u, v, 1, true)\n\n    proc initUnWeightedUnDirectedStaticGraph*(N: int, capacity: int = 0): UnWeightedUnDirectedStaticGraph =\n        result = UnWeightedUnDirectedStaticGraph(\n            src: newSeqOfCap[int32](capacity*2),\n            dst: newSeqOfCap[int32](capacity*2),\n            cost: newSeqOfCap[int](capacity*2),\n            elist: newSeq[(int32, int)](0),\n            start: newSeq[int32](0),\n            len: N\n        )\n    proc add_edge*(g: var UnWeightedUnDirectedStaticGraph, u, v: int) =\n        g.add_edge_static_impl(u, v, 1, false)\n\n    proc static_graph_initialized_check*[T](g: StaticGraph[T]) = assert g.start.len > 0, \"Static Graph must be initialized before use.\"\n\n    iterator `[]`*[T](g: WeightedDirectedStaticGraph[T] or WeightedUnDirectedStaticGraph[T], x: int): (int, T) =\n        g.static_graph_initialized_check()\n        for i in g.start[x]..<g.start[x+1]: yield (g.elist[i][0].int, g.elist[i][1])\n    iterator `[]`*(g: UnWeightedDirectedStaticGraph or UnWeightedUnDirectedStaticGraph, x: int): int =\n        g.static_graph_initialized_check()\n        for i in g.start[x]..<g.start[x+1]: yield g.elist[i][0].int\n\n    iterator to_and_cost*[T](g: DynamicGraph[T], x: int): (int, T) =\n        for e in g.edges[x]: yield (e[0].int, e[1])\n    iterator to_and_cost*[T](g: StaticGraph[T], x: int): (int, T) =\n        g.static_graph_initialized_check()\n        for i in g.start[x]..<g.start[x+1]: yield (g.elist[i][0].int, g.elist[i][1])\n"
# source: https://github.com/zer0-star/Nim-ACL/tree/master/src/atcoder/convolution.nim
ImportExpand "atcoder/convolution" <=== "when not declared ATCODER_CONVOLUTION_HPP:\n  const ATCODER_CONVOLUTION_HPP* = 1\n\n  import std/math\n  import std/sequtils\n  import std/sugar\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      #      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  \n  when not declared ATCODER_INTERNAL_BITOP_HPP:\n    const ATCODER_INTERNAL_BITOP_HPP* = 1\n    import std/bitops\n  \n  #ifdef _MSC_VER\n  #include <intrin.h>\n  #endif\n  \n  # @param n `0 <= n`\n  # @return minimum non-negative `x` s.t. `n <= 2**x`\n    proc ceil_pow2*(n:SomeInteger):int =\n      var x = 0\n      while (1.uint shl x) < n.uint: x.inc\n      return x\n  # @param n `1 <= n`\n  # @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`\n    proc bsf*(n:SomeInteger):int =\n      return countTrailingZeroBits(n)\n  \n  when not declared ATCODER_ELEMENT_CONCEPTS_HPP:\n    const ATCODER_ELEMENT_CONCEPTS_HPP* = 1\n    proc inv*[T:SomeFloat](a:T):auto = T(1) / a\n    proc init*(self:typedesc[SomeFloat], a:SomeNumber):auto = self(a)\n    type AdditiveGroupElem* = concept x, y, type T\n      x + y\n      x - y\n      -x\n      T(0)\n    type MultiplicativeGroupElem* = concept x, y, type T\n      x * y\n      x / y\n  #    x.inv()\n      T(1)\n    type RingElem* = concept x, y, type T\n      x + y\n      x - y\n      -x\n      x * y\n      T(0)\n      T(1)\n    type FieldElem* = concept x, y, type T\n      x + y\n      x - y\n      x * y\n      x / y\n      -x\n  #    x.inv()\n      T(0)\n      T(1)\n    type FiniteFieldElem* = concept x, type T\n      T is FieldElem\n      T.mod\n      T.mod() is int\n      x.pow(1000000)\n    type hasInf* = concept x, type T\n      T(Inf)\n  \n\n  type fft_info*[mint:FiniteFieldElem; g, rank2:static[int]] = object\n    root, iroot: array[rank2 + 1, mint]\n    rate2, irate2: array[max(0, rank2 - 2 + 1), mint]\n    rate3, irate3: array[max(0, rank2 - 3 + 1), mint]\n\n  proc initFFTInfo*[mint:FiniteFieldElem]():auto =\n    const g = primitive_root[mint.mod]()\n    const rank2 = bsf(mint.mod - 1)\n    var root, iroot:array[rank2 + 1, mint]\n    var rate2, irate2: array[max(0, rank2 - 2 + 1), mint]\n    var rate3, irate3: array[max(0, rank2 - 3 + 1), mint]\n    mixin init, inv\n\n    root[rank2] = mint.init(g).pow((mint.mod - 1) shr rank2)\n    iroot[rank2] = root[rank2].inv()\n    for i in countdown(rank2 - 1, 0):\n      root[i] = root[i + 1] * root[i + 1];\n      iroot[i] = iroot[i + 1] * iroot[i + 1];\n  \n    block:\n      var\n        prod = mint.init(1)\n        iprod = mint.init(1)\n      for i in 0..rank2 - 2:\n        rate2[i] = root[i + 2] * prod\n        irate2[i] = iroot[i + 2] * iprod\n        prod *= iroot[i + 2]\n        iprod *= root[i + 2]\n    block:\n      var\n        prod = mint.init(1)\n        iprod = mint.init(1)\n      for i in 0..rank2 - 3:\n        rate3[i] = root[i + 3] * prod;\n        irate3[i] = iroot[i + 3] * iprod;\n        prod *= iroot[i + 3];\n        iprod *= root[i + 3];\n    return fft_info[mint, g, rank2](root:root, iroot:iroot, rate2:rate2, irate2:irate2, rate3: rate3, irate3:irate3)\n  \n  proc butterfly*[mint:FiniteFieldElem](a:var seq[mint]) =\n    mixin init\n    let n = a.len\n    let h = ceil_pow2(n)\n\n    const info = initFFTInfo[mint]()\n\n    var len = 0  # a[i, i+(n>>len), i+2*(n>>len), ..] is transformed\n    while len < h:\n      if h - len == 1:\n        let p = 1 shl (h - len - 1)\n        var rot = mint.init(1)\n        for s in 0..<(1 shl len):\n          var offset = s shl (h - len)\n          for i in 0..<p:\n            let l = a[i + offset]\n            let r = a[i + offset + p] * rot\n            a[i + offset] = l + r\n            a[i + offset + p] = l - r\n          if s + 1 != (1 shl len):\n            rot *= info.rate2[bsf(not s.uint)]\n        len.inc\n      else:\n        # 4-base\n        let p = 1 shl (h - len - 2)\n        var\n          rot = mint.init(1)\n          imag = info.root[2]\n        for s in 0..<(1 shl len):\n          let\n            rot2 = rot * rot\n            rot3 = rot2 * rot\n            offset = s shl (h - len)\n          for i in 0..<p:\n            let\n              mod2 = (mint.mod() * mint.mod()).uint\n              a0 = (a[i + offset].val()).uint\n              a1 = (a[i + offset + p].val() * rot.val()).uint\n              a2 = (a[i + offset + 2 * p].val() * rot2.val()).uint\n              a3 = (a[i + offset + 3 * p].val() * rot3.val()).uint\n              a1na3imag = (mint.init(a1 + mod2 - a3).val() * imag.val()).uint\n              na2 = mod2 - a2\n            a[i + offset] = mint.init(a0 + a2 + a1 + a3)\n            a[i + offset + 1 * p] = mint.init(a0 + a2 + (2.uint * mod2 - (a1 + a3)))\n            a[i + offset + 2 * p] = mint.init(a0 + na2 + a1na3imag)\n            a[i + offset + 3 * p] = mint.init(a0 + na2 + (mod2 - a1na3imag))\n          if s + 1 != (1 shl len):\n            rot *= info.rate3[bsf(not s.uint)]\n        len += 2\n  \n  proc butterfly_inv*[mint:FiniteFieldElem](a:var seq[mint]) =\n    let n = a.len\n    let h = ceilpow2(n)\n    mixin init\n\n    const info = initFFTInfo[mint]()\n  \n    var len = h;  # a[i, i+(n>>len), i+2*(n>>len), ..] is transformed\n    while len > 0:\n      if len == 1:\n        let p = 1 shl (h - len)\n        var irot = mint.init(1)\n        for s in 0..<(1 shl (len - 1)):\n          let offset = s shl (h - len + 1)\n          for i in 0..<p:\n            let\n              l = a[i + offset]\n              r = a[i + offset + p]\n            a[i + offset] = l + r\n            a[i + offset + p] = mint.init((mint.mod() + l.val() - r.val()) * irot.val())\n          if s + 1 != (1 shl (len - 1)):\n            irot *= info.irate2[bsf(not s.uint)]\n        len.dec\n      else:\n        # 4-base\n        let p = 1 shl (h - len);\n        var irot = mint.init(1)\n        let iimag = info.iroot[2]\n        for s in 0..<(1 shl (len - 2)):\n          let\n            irot2 = irot * irot\n            irot3 = irot2 * irot\n            offset = s shl (h - len + 2)\n          for i in 0..<p:\n            let\n              a0 = a[i + offset + 0 * p].val().uint\n              a1 = a[i + offset + 1 * p].val().uint\n              a2 = a[i + offset + 2 * p].val().uint\n              a3 = a[i + offset + 3 * p].val().uint\n              a2na3iimag = mint.init((mint.mod.uint + a2 - a3) * iimag.val().uint).val().uint\n  \n            a[i + offset] = mint.init(a0 + a1 + a2 + a3)\n            a[i + offset + 1 * p] = mint.init((a0 + (mint.mod().uint - a1) + a2na3iimag) * irot.val().uint)\n            a[i + offset + 2 * p] = mint.init((a0 + a1 + (mint.mod().uint - a2) + (mint.mod().uint - a3)) * irot2.val().uint)\n            a[i + offset + 3 * p] = mint.init((a0 + (mint.mod().uint - a1) + (mint.mod().uint - a2na3iimag)) * irot3.val().uint)\n          if s + 1 != (1 shl (len - 2)):\n            irot *= info.irate3[bsf(not s.uint)]\n        len -= 2\n\n  proc convolution_naive*[mint:FiniteFieldElem](a, b:seq[mint]):seq[mint] =\n    mixin `+=`\n    let (n, m) = (a.len, b.len)\n    result = newSeq[mint](n + m - 1)\n    if n < m:\n      for j in 0..<m:\n        for i in 0..<n:\n          result[i + j] += a[i] * b[j]\n    else:\n      for i in 0..<n:\n        for j in 0..<m:\n          result[i + j] += a[i] * b[j]\n\n  proc convolution_fft*[mint:FiniteFieldElem](a, b:seq[mint]):seq[mint] =\n    mixin init, inv\n    let\n      (n, m) = (a.len, b.len)\n      z = 1 shl ceil_pow2(n + m - 1)\n    var (a, b) = (a, b)\n    a.setLen(z)\n    butterfly(a)\n    b.setLen(z)\n    butterfly(b)\n    for i in 0..<z:\n      a[i] *= b[i];\n    butterfly_inv(a)\n    a.setLen(n + m - 1)\n    let iz = mint.init(z).inv()\n    for i in 0..<n + m - 1: a[i] *= iz\n    return a\n\n  proc convolution*[mint:FiniteFieldElem](a, b:seq[mint]):seq[mint] =\n    let (n, m) = (a.len, b.len)\n    if n == 0 or m == 0: return\n    if min(n, m) <= 60: return convolution_naive(a, b)\n    return convolution_fft(a, b)\n\n  when not declared ATCODER_MODINT_HPP:\n    const ATCODER_MODINT_HPP* = 1\n    import std/macros\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    \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  \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  \n  proc convolution*[T:SomeInteger](a, b:seq[T], M:static[uint] = 998244353):seq[T] =\n    let (n, m) = (a.len, b.len)\n    if n == 0 or m == 0: return newSeq[T]()\n  \n    type mint = StaticModInt[M.int]\n    static:\n      assert mint is FiniteFieldElem\n    return convolution(\n      a.map((x:T) => mint.init(x)), \n      b.map((x:T) => mint.init(x))\n    ).map((x:mint) => T(x.val()))\n\n  proc convolution_ll*(a, b:seq[int]):seq[int] =\n    let (n, m) = (a.len, b.len)\n    if n == 0 or m == 0: return newSeq[int]()\n    const\n      MOD1:uint = 754974721  # 2^24\n      MOD2:uint = 167772161  # 2^25\n      MOD3:uint = 469762049  # 2^26\n      M2M3 = MOD2 * MOD3\n      M1M3 = MOD1 * MOD3\n      M1M2 = MOD1 * MOD2\n      M1M2M3 = MOD1 * MOD2 * MOD3\n\n      i1 = inv_gcd((MOD2 * MOD3).int, MOD1.int)[1].uint\n      i2 = inv_gcd((MOD1 * MOD3).int, MOD2.int)[1].uint\n      i3 = inv_gcd((MOD1 * MOD2).int, MOD3.int)[1].uint\n    \n    let\n      c1 = convolution(a, b, MOD1)\n      c2 = convolution(a, b, MOD2)\n      c3 = convolution(a, b, MOD3)\n  \n    var c = newSeq[int](n + m - 1)\n    for i in 0..<n + m - 1:\n      var x = 0.uint\n      x += (c1[i].uint * i1) mod MOD1 * M2M3\n      x += (c2[i].uint * i2) mod MOD2 * M1M3\n      x += (c3[i].uint * i3) mod MOD3 * M1M2\n      # B = 2^63, -B <= x, r(real value) < B\n      # (x, x - M, x - 2M, or x - 3M) = r (mod 2B)\n      # r = c1[i] (mod MOD1)\n      # focus on MOD1\n      # r = x, x - M', x - 2M', x - 3M' (M' = M % 2^64) (mod 2B)\n      # r = x,\n      #   x - M' + (0 or 2B),\n      #   x - 2M' + (0, 2B or 4B),\n      #   x - 3M' + (0, 2B, 4B or 6B) (without mod!)\n      # (r - x) = 0, (0)\n      #       - M' + (0 or 2B), (1)\n      #       -2M' + (0 or 2B or 4B), (2)\n      #       -3M' + (0 or 2B or 4B or 6B) (3) (mod MOD1)\n      # we checked that\n      #   ((1) mod MOD1) mod 5 = 2\n      #   ((2) mod MOD1) mod 5 = 3\n      #   ((3) mod MOD1) mod 5 = 4\n#      var diff = c1[i] - floorMod(x.int, MOD1.int)\n      var diff = c1[i] - floorMod(cast[int](x), MOD1.int)\n      if diff < 0: diff += MOD1.int\n      const offset = [0'u, 0'u, M1M2M3, 2'u * M1M2M3, 3'u * M1M2M3]\n      x -= offset[diff mod 5]\n      c[i] = cast[int](x)\n    return c\n"

# {.checks: off.}

var n = input(int)
var g = initUnWeightedUnDirectedStaticGraph(n)
for i in 0..<n-1:
    var u, v = input(int)-1
    g.add_edge(u, v)
g.build
var s = input(string).mapIt(if it == '1': 1 else: -1)

var removed = newSeqWith(n, false)
var sz = newSeqWith(n, 0)

var ans = 0
proc mul(f, g: seq[int]): seq[int] = convolution_ll(f, g)
proc add(f, g: seq[int], fg, gg: int): (seq[int], int) =
    var geta = max(fg, gg)
    var ans = newSeqWith(max(f.len - fg + geta, g.len - gg + geta), 0)
    for i in 0..<f.len: ans[i - fg + geta] += f[i]
    for i in 0..<g.len: ans[i - gg + geta] += g[i]
    return (ans, geta)
proc minus(f: seq[int]): seq[int] = f.mapIt(-it)

proc centroid_decompotision(x: int) =
    proc calc_total_size(u, par: int): int =
        result = 1
        for v in g[u]:
            if v == par or removed[v]: continue
            result += calc_total_size(v, u)
    var total_size = calc_total_size(x, -1)
    var m = (total_size + 1) // 2
    proc find_centroid(u, par: int): (int, int) =
        result = (-1, INFL)
        sz[u] = 1
        for v in g[u]:
            if v == par or removed[v]: continue
            var (c, mx) = find_centroid(v, u)
            sz[u] += sz[v]
            if chmin(result[1], mx): result[0] = c
        if sz[u] >= m and chmin(result[1], sz[u]):
            result[0] = u; result[1] = sz[u]
    var (c, _) = find_centroid(x, -1)
    var f = newSeq[seq[int]]()
    var getas = newSeq[int]()
    for v in g[c]:
        if removed[v]: continue
        proc calc_geta(u, par, x: int): int =
            result = x
            for v in g[u]:
                if v == par or removed[v]: continue
                result.min = calc_geta(v, u, x + s[v])
        var geta = max(0, -calc_geta(v, c, s[v]))
        f.add(newSeqWith(geta+sz[v]+1, 0))
        getas.add(geta)
        proc calc_f(u, par, x: int) =
            f[^1][x+geta] += 1
            for v in g[u]:
                if v == par or removed[v]: continue
                calc_f(v, u, x + s[v])
        calc_f(v, c, s[v])

    for i in 0..<f.len: debug(getas[i], f[i])
    var gmax = (if getas.len > 0: getas.max else: 0)
    debug(sz[x], gmax)
    var total = newSeqWith(gmax+sz[x], 0)
    for i in 0..<f.len:
        for j in 0..<f[i].len:
            if f[i][j] != 0:
                debug(j, j-getas[i]+gmax)
                total[j-getas[i]+gmax] += f[i][j]
    for i in gmax+1-s[c]..<total.len: ans += total[i]

    total = mul(total, total)
    gmax *= 2
    for i in 0..<f.len:
        f[i] = mul(f[i], f[i])
        getas[i] *= 2
    for i in 0..<f.len:
        for j in 0..<f[i].len:
            if f[i][j] != 0: total[j-getas[i]+gmax] -= f[i][j]
    for i in gmax+1-s[c]..<total.len: ans += total[i] // 2

    removed[c] = true
    debug(c)
    for v in g[c]:
        if removed[v]: continue
        centroid_decompotision(v)
centroid_decompotision(0)
print(ans + s.count(1))
0