$F(x)$ を求める際はFFTを用いるが、二分木の要領で、隣り合う要素同士を順次マージして
なるべく長い配列を何度もマージしないように工夫すると、全体を $O(N \log^2{N})$ で求められる。
な~んか、自前のFFTライブラリ遅いんだよな……
import os
import sys
from collections import deque
import numpy as np
input = sys.stdin.buffer.readline
# MOD 998244353 前提
MOD = 998244353
SUM_E = np.array(
[911660635, 509520358, 369330050, 332049552, 983190778, 123842337, 238493703, 975955924, 603855026, 856644456,
131300601, 842657263, 730768835, 942482514, 806263778, 151565301, 510815449, 503497456, 743006876, 741047443,
56250497, 867605899, 0, 0, 0, 0, 0, 0, 0, 0], np.int64)
SUM_IE = np.array(
[86583718, 372528824, 373294451, 645684063, 112220581, 692852209, 155456985, 797128860, 90816748, 860285882,
927414960, 354738543, 109331171, 293255632, 535113200, 308540755, 121186627, 608385704, 438932459, 359477183,
824071951, 103369235, 0, 0, 0, 0, 0, 0, 0, 0], np.int64)
def convolution(aaa, bbb):
def bit_length(n):
x = 0
while 1 << x < n:
x += 1
return x
def bit_scan_forward(n):
x = 0
while n & 1 == 0:
n >>= 1
x += 1
return x
def mod_pow(x, a, MOD):
ret = 1
cur = x
while a > 0:
if a & 1:
ret = ret * cur % MOD
cur = cur * cur % MOD
a >>= 1
return ret
def butterfly(aaa, mod, sum_e):
n = aaa.size
h = bit_length(n)
for ph in range(1, h + 1):
w = 1 << (ph - 1)
p = 1 << (h - ph)
now = 1
for s in range(w):
offset = s << (h - ph + 1)
for i in range(p):
l = aaa[i + offset]
r = aaa[i + offset + p] * now % mod
aaa[i + offset] = (l + r) % mod
aaa[i + offset + p] = (l - r) % mod
now = now * sum_e[bit_scan_forward(~s)] % mod
def butterfly_inv(aaa, mod, sum_ie):
n = aaa.size
h = bit_length(n)
for ph in range(h, 0, -1):
w = 1 << (ph - 1)
p = 1 << (h - ph)
inow = 1
for s in range(w):
offset = s << (h - ph + 1)
for i in range(p):
l = aaa[i + offset]
r = aaa[i + offset + p]
aaa[i + offset] = (l + r) % mod
aaa[i + offset + p] = ((l - r) * inow) % mod
inow = inow * sum_ie[bit_scan_forward(~s)] % mod
n = aaa.size
m = bbb.size
k = n + m - 1
z = 1 << bit_length(k)
raaa = np.zeros(z, np.int64)
rbbb = np.zeros(z, np.int64)
raaa[:n] = aaa
rbbb[:m] = bbb
butterfly(raaa, MOD, SUM_E)
butterfly(rbbb, MOD, SUM_E)
for i in range(z):
raaa[i] = raaa[i] * rbbb[i] % MOD
butterfly_inv(raaa, MOD, SUM_IE)
iz = mod_pow(z, MOD - 2, MOD)
for i in range(k):
raaa[i] = raaa[i] * iz % MOD
return raaa[:k]
SIGNATURE = '(i8[:],i8[:])'
if sys.argv[-1] == 'ONLINE_JUDGE':
from numba.pycc import CC
cc = CC('my_module')
cc.export('convolution', SIGNATURE)(convolution)
cc.compile()
exit()
if os.name == 'posix':
# noinspection PyUnresolvedReferences
from my_module import convolution
else:
from numba import njit
convolution = njit(SIGNATURE, cache=True)(convolution)
print('compiled', file=sys.stderr)
n = int(input())
aaa = list(map(int, input().split()))
q = deque()
s = 0
for a in aaa:
q.append(np.array([1, a], np.int64))
s += a
while len(q) > 1:
arr1 = q.popleft()
arr2 = q.popleft()
arr3 = convolution(arr1, arr2)
q.append(arr3)
res = q[0]
f = 1
for i in range(2, n + 1):
f = f * i % MOD
res[i] = res[i] * f % MOD
spk = 1
for i in range(s, s - n, -1):
spk *= i
spk %= MOD
spk_inv = [pow(spk, -1, MOD)]
for i in range(s - n + 1, s + 1):
spk_inv.append(spk_inv[-1] * i % MOD)
spk_inv.reverse()
ans = 1
for i in range(1, n + 1):
ans += res[i] * spk_inv[i]
ans %= MOD
print(ans)