int n, sa, sb; int a[kMaxN], b[kMaxN], fac[kMaxN], ifac[kMaxN], f[kMaxN][kMaxN];
constexprintqpow(int bs, int64_t idx = kMod - 2){ int ret = 1; for (; idx; idx >>= 1, bs = (int64_t)bs * bs % kMod) if (idx & 1) ret = (int64_t)ret * bs % kMod; return ret; }
inlineintadd(int x, int y){ return (x + y >= kMod ? x + y - kMod : x + y); } inlineintsub(int x, int y){ return (x >= y ? x - y : x - y + kMod); } inlinevoidinc(int &x, int y){ (x += y) >= kMod ? x -= kMod : x; } inlinevoiddec(int &x, int y){ (x -= y) < 0 ? x += kMod : x; }
voidprework(int n = 400){ fac[0] = ifac[0] = 1; for (int i = 1; i <= n; ++i) { fac[i] = 1ll * i * fac[i - 1] % kMod; ifac[i] = qpow(fac[i]); } }
voiddickdreamer(){ std::cin >> n; for (int i = 1; i <= n; ++i) std::cin >> a[i] >> b[i]; prework(); f[0][0] = kMod - 1; for (int i = 1; i <= n; ++i) { for (int j = sa; ~j; --j) { for (int k = sb; ~k; --k) { if (!f[j][k]) continue; int pw = 1; for (int c = 0; c <= b[i] - 1; ++c) { dec(f[j + a[i]][k + c], 1ll * f[j][k] * ifac[c] % kMod * pw % kMod); pw = 1ll * pw * a[i] % kMod; } } } sa += a[i], sb += b[i]; } int ans = 0; for (int i = 1; i <= sa; ++i) { for (int j = 0; j <= sb; ++j) inc(ans, 1ll * sa * qpow(i) % kMod * fac[j] % kMod * qpow(qpow(i), j) % kMod * f[i][j] % kMod); } std::cout << ans << '\n'; }