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
| #include <iostream> #include <algorithm> #include <vector> #define maxn 100010 #define ll long long using namespace std;
const int p = 998244353; ll pow_mod(ll x, ll n) { ll s = 1; for (; n; n >>= 1, x = x * x % p) if (n & 1) s = s * x % p; return s; } 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; }
typedef std::vector<int> Poly; namespace Pol { const int N = 4200000; int a[N], b[N]; 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); } void NTT(int *a, int n, int type) { static int w[N]; ll G = 3, Gi = pow_mod(G, p - 2); for (int i = 0; i < n; ++i) if (i < P[i]) swap(a[i], a[P[i]]); for (int i = 2, m = 1; i <= n; m = i, i *= 2) { int wn = pow_mod(type > 0 ? G : Gi, (p - 1) / i); w[0] = 1; for (int j = 1; j < m; ++j) w[j] = mul(wn, w[j - 1]); for (int j = 0; j < n; j += i) for (int k = 0; k < m; ++k) { int t1 = a[j + k], t2 = mul(a[j + k + m], w[k]); a[j + k] = add(t1, t2); a[j + k + m] = add(t1, p - t2); } } if (type < 0) { ll inv = pow_mod(n, p - 2); for (int i = 0; i < n; ++i) a[i] = inv * a[i] % p; } } Poly Mul(const Poly &A, const Poly &B, int n1, int n2) { int n = 1; 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); NTT(a, n, 1); NTT(b, n, 1); for (int i = 0; i < n; ++i) a[i] = mul(a[i], b[i]); NTT(a, n, -1); 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); NTT(a, n, 1); NTT(b, n, 1); for (int i = 0; i < n; ++i) a[i] = mul(a[i], b[i]); NTT(a, n, -1); Poly ans(len); copy_n(a, len, ans.begin()); reverse(ans.begin(), ans.end()); return ans; } }
int n;
ll pr[maxn], c[maxn], w[maxn], s[maxn], invs[maxn], invpr[maxn]; void solve(int opt, Poly &A, const Poly &B, int l, int r) { if (l + 1 == r) { if (l > 0) { A[l] = 1ll * A[l] * add(1, p - pr[l - 1]) % p * invs[l - 1] % p; A[l] = add(A[l - 1], p - A[l]); if (opt) A[l] = add(A[l], p - c[l - 1]); A[l] = 1ll * A[l] * invpr[l - 1] % p; } return ; } int m = l + r >> 1; solve(opt, A, B, l, m); Poly t1(m - l), t2(r - l); for (int i = l; i < m; ++i) t1[i - l] = A[i]; for (int i = 0; i < r - l; ++i) t2[i] = B[i]; Poly t = Pol::Mul(t1, t2, m - l, r - l); for (int i = m; i < r; ++i) if (i + 1 < n + 1) A[i + 1] = (A[i + 1] + t[i - l]) % p; solve(opt, A, B, m, r); }
void work() { cin >> n; ll inv100 = pow_mod(100, p - 2), ansa, ansb; for (int i = 0; i < n; ++i) cin >> pr[i] >> c[i], pr[i] = pr[i] * inv100 % p; for (int i = 1; i < n; ++i) cin >> w[i], s[i] = add(s[i - 1], w[i]); for (int i = 1; i < n; ++i) invs[i] = pow_mod(s[i], p - 2); for (int i = 0; i < n; ++i) invpr[i] = pow_mod(pr[i], p - 2); Poly A(n + 1), B(n + 1); A[0] = 1; for (int i = 1; i < n; ++i) B[i] = w[i]; solve(0, A, B, 0, n + 1); ansa = A[n]; fill(A.begin(), A.end(), 0); solve(1, A, B, 0, n + 1); ansb = A[n];
cout << p - ansb * pow_mod(ansa, p - 2) % p << "\n"; }
int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int T; cin >> T; while (T--) work(); return 0; }
|