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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
| #include <iostream> #include <vector> #include <algorithm> #include <tuple> #define maxn 100010 #define ll long long using namespace std;
const int p = 998244353; inline int add(int x, int y) { return (x += y) >= p ? x - p : x; } inline int mul(int x, int y) { return 1ll * x * y % p; } inline int add(initializer_list<int> lst) { int s = 0; for (auto t : lst) s = add(s, t); return s; } inline int mul(initializer_list<int> lst) { int s = 1; for (auto t : lst) s = mul(s, t); return s; } int pow_mod(int x, int n) { int s = 1; for (; n; n >>= 1, x = mul(x, x)) if (n & 1) s = mul(s, x); return s; }
typedef std::vector<int> Poly; namespace Pol { inline int add(int a, int b) { return (a += b) >= p ? a -= p : a; } inline int mul(int a, int b) { return 1ll * a * b % p; } const int N = 4200000; int a[N], b[N];
const int G = 3; const int Gi = pow_mod(G, p - 2); int P[N]; void init_P(int n) { int l = 0; while ((1 << l) < n) ++l; for (int i = 0; i < n; ++i) P[i] = (P[i >> 1] >> 1) | ((i & 1) << l - 1); } vector<int> init_W(int n) { vector<int> w(n); w[1] = 1; for (int i = 2; i < n; i <<= 1) { auto w0 = w.begin() + i / 2, w1 = w.begin() + i; int wn = pow_mod(G, (p - 1) / (i << 1)); for (int j = 0; j < i; j += 2) w1[j] = w0[j >> 1], w1[j + 1] = mul(w1[j], wn); } return w; } auto w = init_W(1 << 21); void DIT(int *a, int n) { for (int k = n >> 1; k; k >>= 1) for (int i = 0; i < n; i += k << 1) for (int j = 0; j < k; ++j) { int x = a[i + j], y = a[i + j + k]; a[i + j + k] = mul(add(x, p - y), w[k + j]), a[i + j] = add(x, y); } } void DIF(int *a, int n) { for (int k = 1; k < n; k <<= 1) for (int i = 0; i < n; i += k << 1) for (int j = 0; j < k; ++j) { int x = a[i + j], y = mul(a[i + j + k], w[k + j]); a[i + j + k] = add(x, p - y), a[i + j] = add(x, y); } int inv = pow_mod(n, p - 2); for (int i = 0; i < n; ++i) a[i] = mul(a[i], inv); reverse(a + 1, a + n); } Poly Mul(const Poly &A, const Poly &B) { int n = 1, n1 = A.size(), n2 = B.size(); while (n < n1 + n2 - 1) n <<= 1; init_P(n); for (int i = 0; i < n1; ++i) a[i] = add(A[i], p); for (int i = 0; i < n2; ++i) b[i] = add(B[i], p); fill(a + n1, a + n, 0), fill(b + n2, b + n, 0); DIT(a, n); DIT(b, n); for (int i = 0; i < n; ++i) a[i] = mul(a[i], b[i]); DIF(a, n); Poly ans(n1 + n2 - 1); copy_n(a, n1 + n2 - 1, ans.begin()); return ans; } Poly MMul(const Poly &A, const Poly &B, int len) { int n = 1; while (n < 2 * len - 1) n <<= 1; init_P(n); for (int i = 0; i < len; ++i) a[i] = add(A[i], p); for (int i = 0; i < len; ++i) b[i] = add(B[i], p); fill(a + len, a + n, 0), fill(b + len, b + n, 0); reverse(b, b + len); DIT(a, n); DIT(b, n); for (int i = 0; i < n; ++i) a[i] = mul(a[i], b[i]); DIF(a, n); Poly ans(len); copy_n(a, len, ans.begin()); reverse(ans.begin(), ans.end()); return ans; } }
int fac[maxn], inv[maxn]; void init_C(int n) { fac[0] = 1; for (int i = 1; i <= n; ++i) fac[i] = mul(fac[i - 1], i); inv[n] = pow_mod(fac[n], p - 2); for (int i = n - 1; ~i; --i) inv[i] = mul(inv[i + 1], i + 1); }
int n, a[maxn];
tuple<Poly, Poly, Poly> solve(int l, int r) { if (l == r) { Poly A(a[l] + 1), B, AB; for (int i = 0; i <= a[l]; ++i) A[i] = mul(inv[i], inv[a[l] - i]); B = A; A[0] = add(A[0], p - inv[a[l]]); AB = A; return make_tuple(A, B, AB); } int m = l + r >> 1; auto [lA, lB, lAB] = solve(l, m); auto [rA, rB, rAB] = solve(m + 1, r); Poly A = Pol::Mul(lA, rA), B = Pol::Mul(lB, rB), AB1 = Pol::Mul(lAB, rB), AB2 = Pol::Mul(rAB, lA); int l1 = AB1.size(), l2 = AB2.size(), L = max(l1, l2); Poly AB(L); for (int i = 0; i < L; ++i) { if (i < l1) AB[i] = add(AB[i], AB1[i]); if (i < l2) AB[i] = add(AB[i], AB2[i]); } return make_tuple(A, B, AB); }
int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin >> n; init_C(n); for (int i = 0; i <= n; ++i) cin >> a[i]; auto [A, B, AB] = solve(0, n); int ans = 0; for (int i = 0; i <= n; ++i) ans = add(ans, mul({ fac[i], fac[n - i + 1], AB[i] })); cout << ans << "\n"; return 0; }
|