1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
#include <cstdio> #include <vector> #include <algorithm> using namespace std;
const int LOG = 18, MAXN = 1 << LOG | 1, P = 998244353, G = 3;
int W[LOG][MAXN];
int fpow(int base, int b) { int ret = 1; while (b > 0) { if (b & 1) ret = 1LL * ret * base % P; base = 1LL * base * base % P, b >>= 1; } return ret; }
namespace Poly { int r[MAXN]; inline void init(const int& Lim, const int& L) { for (int i = 1; i < Lim; ++i) r[i] = (r[i>>1] >> 1) | ((i & 1) << (L-1)); }
void NTT(int* f, const int& Lim, const int& type) { for (int i = 1; i < Lim; ++i) if (i < r[i]) swap(f[i], f[r[i]]); for (int k = 0, Mid = 1; Mid < Lim; Mid <<= 1, ++k) { const int* w = W[k]; for (int i = 0; i < Lim; i += Mid << 1) for (int j = 0; j < Mid; ++j) { int f0 = f[i+j], f1 = 1LL * w[j] * f[i+j+Mid] % P; f[i+j] = (f0 + f1) % P, f[i+j+Mid] = (f0 - f1 + P) % P; } } if (type < 0) { int iv = fpow(Lim, P - 2); for (int i = 0; i < Lim; ++i) f[i] = 1LL * f[i] * iv % P; reverse(f + 1, f + Lim); } } }
void PolyPre() { for (int w, i = 0, Mid = 1; i < LOG; ++i, Mid <<= 1) { W[i][0] = 1, w = fpow(G, (P - 1) / (Mid << 1)); for (int j = 1; j < Mid; ++j) W[i][j] = 1LL * w * W[i][j - 1] % P; } }
typedef vector<int> poly;
poly operator * (const poly& f, const poly& g) { static int A[MAXN], B[MAXN]; int Lim = 1, L = 0; while (Lim < int(f.size() + g.size())) Lim <<= 1, ++L; for (int i = 0; i < Lim; ++i) { A[i] = (i < (int) f.size())? f[i]: 0; B[i] = (i < (int) g.size())? g[i]: 0; } Poly::init(Lim, L), Poly::NTT(A, Lim, 1), Poly::NTT(B, Lim, 1); for (int i = 0; i < Lim; ++i) A[i] = 1LL * A[i] * B[i] % P; Poly::NTT(A, Lim, -1); poly h(f.size() + g.size() - 1); for (size_t i = 0; i < h.size(); ++i) h[i] = A[i]; return h; }
int n; int w[MAXN];
poly solve(int L, int R) { if (L == R) { poly g(w[L] + 1); return g[0] = 1, g[w[L]] = P - 1, g; } int Mid = (L + R) / 2; return solve(L, Mid) * solve(Mid + 1, R); }
int main() { #ifndef ONLINE_JUDGE freopen("input.in", "r", stdin); #endif scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", w + i);
PolyPre(); poly f = solve(2, n); int ans = 0; for (int i = 0; i < (int) f.size(); ++i) { int iv = fpow((i + w[1]) % P, P - 2); ans = (ans + 1LL * w[1] * f[i] % P * iv % P) % P; }
printf("%d\n", ans); return 0; }
|