結果

問題 No.3043 括弧列の数え上げ
ユーザー PNJ
提出日時 2025-03-01 02:52:56
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 180 ms / 2,000 ms
コード長 13,160 bytes
コンパイル時間 240 ms
コンパイル使用メモリ 82,496 KB
実行使用メモリ 95,496 KB
最終ジャッジ日時 2025-03-01 02:53:05
合計ジャッジ時間 8,719 ms
ジャッジサーバーID
(参考情報)
judge4 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 45
権限があれば一括ダウンロードができます

ソースコード

diff #

mod = 998244353
n = 10 ** 6
inv = [1 for j in range(n + 1)]
for a in range(2, n + 1):
  # ax + py = 1 <=> rx + p(-x - qy) = -q => x = -(inv[r]) * (p // a)  (r = p % a)
  res = (mod - inv[mod % a]) * (mod // a)
  inv[a] = res % mod

def mod_inv(a, mod = 998244353):
  if mod == 1:
    return 0
  a %= mod
  b, s, t = mod, 1, 0
  while True:
    if a == 1:
      return s
    t -= (b // a) * s
    b %= a
    if b == 1:
      return t + mod
    s -= (a // b) * t
    a %= b

fact = [1 for i in range(n + 1)]
for i in range(1, n + 1):
  fact[i] = fact[i - 1] * i % mod

fact_inv = [1 for i in range(n + 1)]
fact_inv[-1] = pow(fact[-1], mod - 2, mod)
for i in range(n, 0, -1):
  fact_inv[i - 1] = fact_inv[i] * i % mod

def binom(n, r):
  if n < r or n < 0 or r < 0:
    return 0
  res = fact_inv[n - r] * fact_inv[r] % mod
  res *= fact[n]
  res %= mod
  return res

def Garner(Rem, MOD, mod):
  Mod = MOD[:]
  Rem.append(0)
  Mod.append(mod)
  n = len(Mod)
  coffs = [1] * n
  constants = [0] * n
  for i in range(n - 1):
    v = (Rem[i] - constants[i]) * mod_inv(coffs[i], Mod[i]) % Mod[i]
    for j in range(i + 1, n):
      constants[j] = (constants[j] + coffs[j] * v) % Mod[j]
      coffs[j] = (coffs[j] * Mod[i]) % Mod[j]
  return constants[-1]

import random
def Tonelli_Shanks(a, p = 998244353):
  a %= p
  if a < 2:
    return a
  if pow(a, (p - 1) // 2, p) != 1:
    return -1
  if p % 4 == 3:
    return pow(a, (p + 1) // 4, p)
  
  b = 1
  if p == 998244353:
    b = 3
  else:
    while pow(b, (p - 1) // 2, p) == 1:
      b = random.randint(2, p - 1)
  
  q = p - 1
  Q = 0
  while q % 2 == 0:
    Q += 1
    q >>= 1
  
  x = pow(a, (q + 1) // 2, p)
  b = pow(b, q, p)

  shift = 2
  while x * x % p != a:
    error = pow(a, -1, p) * x * x % p
    if pow(error, 1 << (Q - shift), p) != 1:
      x = x * b % p
    b = b * b % p
    shift += 1
  
  return x

def NTT_info(mod):
  if mod == 998244353:
    return (23, 31, 0)
  if mod == 120586241:
    return (20, 74066978, 1)
  if mod == 167772161:
    return (25, 17, 2)
  if mod == 469762049:
    return (26, 30, 3)
  if mod == 754974721:
    return (24, 362, 4)
  if mod == 880803841:
    return (23, 211, 5)
  if mod == 924844033:
    return (21, 44009197, 6)
  if mod == 943718401:
    return (22, 663003469, 7)
  if mod == 1045430273:
    return (20, 363, 8)
  if mod == 1051721729:
    return (20, 330, 9)
  if mod == 1053818881:
    return (20, 2789, 10)
  return (0, -1, -1)

def prepared_fft(mod = 998244353):
  rank2 = NTT_info(mod)[0]
  root, iroot = [0] * 30, [0] * 30
  rate2, irate2 = [0] * 30, [0] * 30
  rate3, irate3 = [0] * 30, [0] * 30

  root[rank2] = NTT_info(mod)[1]
  iroot[rank2] = pow(root[rank2], mod - 2, mod)
  for i in range(rank2 - 1, -1, -1):
    root[i] = root[i + 1] * root[i + 1] % mod
    iroot[i] = iroot[i + 1] * iroot[i + 1] % mod

  prod, iprod = 1, 1
  for i in range(rank2 - 1):
    rate2[i] = root[i + 2] * prod % mod
    irate2[i] = iroot[i + 2] * iprod % mod
    prod = prod * iroot[i + 2] % mod
    iprod = iprod * root[i + 2] % mod
  
  prod, iprod = 1, 1
  for i in range(rank2 - 2):
    rate3[i] = root[i + 3] * prod % mod
    irate3[i] = iroot[i + 3] * iprod % mod
    prod = prod * iroot[i + 3] % mod
    iprod = iprod * root[i + 3] % mod
  
  return root, iroot, rate2, irate2, rate3, irate3

root, iroot, rate2, irate2, rate3, irate3 = [[] for _ in range(11)], [[] for _ in range(11)], [[] for _ in range(11)], [[] for _ in range(11)], [[] for _ in range(11)], [[] for _ in range(11)]

def ntt(a, inverse = 0, mod = 998244353):
  idx = NTT_info(mod)[2]
  if len(root[idx]) == 0:
    root[idx], iroot[idx], rate2[idx], irate2[idx], rate3[idx], irate3[idx] = prepared_fft(mod)
  n = len(a)
  h = (n - 1).bit_length()
  assert (n == 1 << h)
  if inverse == 0:
    le = 0
    while le < h:
      if h - le == 1:
        p = 1 << (h - le - 1)
        rot = 1
        for s in range(1 << le):
          offset = s << (h - le)
          for i in range(p):
            l = a[i + offset]
            r = a[i + offset + p] * rot % mod
            a[i + offset] = (l + r) % mod
            a[i + offset + p] = (l - r) % mod
          rot = rot * rate2[idx][((~s & -~s) - 1).bit_length()] % mod
        le += 1
      else:
        p = 1 << (h - le - 2)
        rot, imag = 1, root[idx][2]
        for s in range(1 << le):
          rot2 = rot * rot % mod
          rot3 = rot2 * rot % mod
          offset = s << (h - le)
          for i in range(p):
            a0 = a[i + offset]
            a1 = a[i + offset + p] * rot
            a2 = a[i + offset + p * 2] * rot2
            a3 = a[i + offset + p * 3] * rot3
            a1na3imag = (a1 - a3) % mod * imag
            a[i + offset] = (a0 + a2 + a1 + a3) % mod
            a[i + offset + p] = (a0 + a2 - a1 - a3) % mod
            a[i + offset + p * 2] = (a0 - a2 + a1na3imag) % mod
            a[i + offset + p * 3] = (a0 - a2 - a1na3imag) % mod
          rot = rot * rate3[idx][((~s & -~s) - 1).bit_length()] % mod
        le += 2
  else:
    coef = pow(n, mod - 2, mod)
    for i in range(n):
      a[i] = a[i] * coef % mod
    le = h
    while le:
      if le == 1:
        p = 1 << (h - le)
        irot = 1
        for s in range(1 << (le - 1)):
          offset = s << (h - le + 1)
          for i in range(p):
            l = a[i + offset]
            r = a[i + offset + p]
            a[i + offset] = (l + r) % mod
            a[i + offset + p] = (l - r) * irot % mod
          irot = irot * irate2[idx][((~s & -~s) - 1).bit_length()] % mod
        le -= 1
      else:
        p = 1 << (h - le)
        irot, iimag = 1, iroot[idx][2]
        for s in range(1 << (le - 2)):
          irot2 = irot * irot % mod
          irot3 = irot2 * irot % mod
          offset = s << (h - le + 2)
          for i in range(p):
            a0 = a[i + offset]
            a1 = a[i + offset + p]
            a2 = a[i + offset + p * 2]
            a3 = a[i + offset + p * 3]
            a2na3iimag = (a2 - a3) * iimag % mod
            a[i + offset] = (a0 + a1 + a2 + a3) % mod
            a[i + offset + p] = (a0 - a1 + a2na3iimag) * irot % mod
            a[i + offset + p * 2] = (a0 + a1 - a2 - a3) * irot2 % mod
            a[i + offset + p * 3] = (a0 - a1 - a2na3iimag) * irot3 % mod
          irot *= irate3[idx][((~s & -~s) - 1).bit_length()]
          irot %= mod
        le -= 2

def transposed_ntt(a, inverse = 0, mod = 998244353):
  # bit_reverse fft の転置
  n = len(a)
  if inverse == 0:
    ntt(a, 1, mod)
    for i in range(1, n // 2):
      a[i], a[n - i] = a[n - i], a[i]
    for i in range(n):
      a[i] = a[i] * n % mod
    return
  else:
    for i in range(1, n // 2):
      a[i], a[n - i] = a[n - i], a[i]
    ntt(a, 0, mod)
    n_inv = pow(n, mod - 2, mod)
    for i in range(n):
      a[i] = a[i] * n_inv % mod
    return

def convolution_naive(a, b, mod = 998244353):
  res = [0] * (len(a) + len(b) - 1)
  for i in range(len(a)):
    for j in range(len(b)):
      res[i + j] = (res[i + j] + a[i] * b[j] % mod) % mod
  return res

def convolution_ntt(a, b, mod = 998244353):
  s = a[:]
  t = b[:]
  n = len(s)
  m = len(t)
  if min(n, m) <= 60:
    return convolution_naive(s, t, mod)
  le = 1
  while le < n + m - 1:
    le *= 2
  s += [0] * (le - n)
  t += [0] * (le - m)
  ntt(s, 0, mod)
  ntt(t, 0, mod)
  for i in range(le):
    s[i] = s[i] * t[i] % mod
  ntt(s, 1, mod)
  s = s[:n + m - 1]
  return s

def convolution_garner(f, g, mod):
  MOD = [167772161, 469762049, 754974721]
  flag = 0
  if (mod - 1) * (mod - 1) * min(len(f), len(g)) >= 167772161 * 469762049 * 754974721:
    MOD += [880803841, 998244353]
    flag = 1
  H = []
  for i in range(len(MOD)):
    H.append(convolution_ntt(f, g, MOD[i]))
  h = []
  for i in range(len(H[0])):
    Rem = [H[0][i], H[1][i], H[2][i]]
    if flag:
      Rem += [H[3][i], H[4][i]]
    h.append(Garner(Rem, MOD, mod) % mod)
  return h

def convolution(f, g, mod = 998244353):
  if NTT_info(mod)[1] == -1:
    return convolution_garner(f, g, mod)
  return convolution_ntt(f, g, mod)

def fps_inv(f, deg = -1, mod = 998244353):
  assert (f[0] != 0)
  if deg == -1:
    deg = len(f)
  n = len(f)
  # ntt_prime
  if NTT_info(mod)[2] != -1:
    g = [mod_inv(f[0], mod)] + [0 for _ in range(deg - 1)]
    le = 1
    while le < deg:
      a = [0 for _ in range(2 * le)]
      b = [0 for _ in range(2 * le)]
      for i in range(min(n, 2 * le)):
        a[i] = f[i]
      for i in range(le):
        b[i] = g[i]
      ntt(a, 0, mod)
      ntt(b, 0, mod)
      for i in range(2 * le):
        a[i] = a[i] * b[i] % mod
      ntt(a, 1, mod)
      for i in range(le):
        a[i] = 0
      ntt(a, 0, mod)
      for i in range(2 * le):
        a[i] = a[i] * b[i] % mod
      ntt(a, 1, mod)
      for j in range(le, min(deg, 2 * le)):
        g[j] = (mod - a[j]) % mod
      le *= 2
    return g
  # not ntt prime
  # doubling
  else:
    g = [0 for _ in range(deg)]
    g[0] = mod_inv(f[0], mod)
    gg = []
    le = 1
    while le < deg:
      gg = convolution(g[:le], g[:le])
      ff = f[:min(2 * le, n)]
      gg = convolution(ff, gg)
      for i in range(min(deg, 2 * le)):
        g[i] = (g[i] + g[i] - gg[i]) % mod
      le *= 2
    return g[:deg]

def fps_exp(f, deg = -1, mod = 998244353):
  if deg == -1:
    deg = len(f)
  n = len(f)
  assert (n > 0)
  assert (f[0] == 0)
  # ntt_prime
  if NTT_info(mod)[2] != -1:
    g = [1, 0]
    if len(f) > 1:
      g[1] = f[1]
    h = [1]
    p = []
    q = [1, 1]
    le = 2
    while le < deg:
      y = g + [0] * le
      ntt(y, 0, mod)
      p = q[:]
      z = [y[i] * p[i] for i in range(le)]
      ntt(z, 1, mod)
      for i in range(le // 2):
        z[i] = 0
      ntt(z, 0, mod)
      for i in range(len(p)):
        z[i] = z[i] * (-p[i]) % mod
      ntt(z, 1, mod)
      for i in range(le // 2, le):
        h.append(z[i])
      q = h + [0] * le
      ntt(q, 0, mod)

      x = [0 for _ in range(le)]
      for i in range(le - 1):
        x[i] = f[i + 1] * (i + 1) % mod
      ntt(x, 0, mod)
      for i in range(le):
        x[i] = x[i] * y[i] % mod
      ntt(x, 1, mod)

      for i in range(le - 1):
        x[i] = (x[i] - g[i + 1] * (i + 1)) % mod

      x += [0] * le
      for i in range(le - 1):
        x[le + i], x[i] = x[i], 0
      ntt(x, 0, mod)
      for i in range(2 * le):
        x[i] = x[i] * q[i] % mod
      ntt(x, 1, mod)
      for i in range(len(x) - 2, -1, -1):
        x[i + 1] = x[i] * mod_inv(i + 1, mod) % mod
      for i in range(le, min(n, 2 * le)):
        x[i] += f[i]
      for i in range(le):
        x[i] = 0
      ntt(x, 0, mod)
      for i in range(2 * le):
        x[i] = x[i] * y[i] % mod
      ntt(x, 1, mod)
      for i in range(le, len(x)):
        g.append(x[i])
      le *= 2
    return g[:deg]
  # not ntt prime
  # Newton's method
  else:
    log = 0
    while (1 << log) < deg:
      log += 1
    ff = [0 for _ in range(1 << log)]
    df = [0 for _ in range(1 << log)]
    for i in range(min(n, (1 << log))):
      ff[i] = f[i]
      if i > 0:
        df[i - 1] = i * f[i] % mod
    g, h = [1], [1]
    le = 1
    for _ in range(log):
      p = convolution(g, h)[:le]
      p = convolution(p, h)[:le]
      while len(h) < le:
        h.append(0)
      for i in range(le):
        h[i] = (2 * h[i] - p[i]) % mod
      p = df[:(le - 1)][:]
      p = convolution(g, p)
      p.append(0)
      for i in range(2 * le - 1):
        p[i] = (mod - p[i]) % mod
      for i in range(le - 1):
        p[i] = (p[i] + g[i + 1] * (i + 1)) % mod
      p = convolution(p, h)[:2 * le - 1]
      for i in range(le - 1):
        p[i] = (p[i] + df[i]) % mod
      p.append(0)
      for i in range(2 * le - 2, -1, -1):
        p[i + 1] = p[i] * mod_inv(i + 1, mod) % mod
      p[0] = 0
      for i in range(2 * le):
        p[i] = (ff[i] - p[i]) % mod
      p[0] = 1
      g = convolution(g, p)[:2 * le]
      le *= 2
    return g[:deg]

def fps_log(f, deg = -1, mod = 998244353):
  assert (f[0] == 1)
  if deg == -1:
    deg = len(f)
  n = len(f)
  df = [0 for _ in range(deg)]
  for i in range(1, min(deg + 1, n)):
    df[i - 1] = f[i] * i % mod
  f_inv = fps_inv(f, deg, mod)
  res = convolution(df, f_inv, mod)[:deg]
  for i in range(deg - 2, -1, -1):
    res[i + 1] = res[i] * mod_inv(i + 1) % mod
  res[0] = 0
  return res

def fps_pow(f, k, deg = -1, mod = 998244353):
  if deg == -1:
    deg = len(f)
  if k == 0:
    return [1] + [0] * (deg - 1)
  n = len(f)
  d = 0
  while d < min(deg, n):
    if f[d]:
      break
    d += 1
  if d * k >= deg or d == n:
    return [0] * deg
  a = f[d]
  a_inv = mod_inv(a, mod)
  g = [0 for _ in range(deg - d * k)]
  for i in range(min(deg - d * k, n - d)):
    g[i] = f[i + d] * a_inv % mod
  g = fps_log(g)
  for i in range(deg - d * k):
    g[i] = g[i] * k % mod
  g = fps_exp(g)
  a = pow(a, k, mod)
  res = [0] * deg
  for i in range(deg - d * k):
    res[i + d * k] = g[i] * a % mod
  return res

def Catalan(n):
  return (binom(2 * n, n) - binom(2 * n, n - 1)) % mod

N = int(input())
ans = 0
if N % 2:
  print(ans)
  exit()
for i in range(4, N + 1, 2):
  res = ((i - 2) // 2) * Catalan((i - 1) // 2)
  res = res * Catalan((N - i) // 2) % mod
  res = res * (N - i + 1) % mod
  ans = (ans + res) % mod
print(ans)
0