#include <bits/stdc++.h>
// iostream is too mainstream
#include <cstdio>
// bitch please
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <list>
#include <cmath>
#include <iomanip>
#include <time.h>
#define dibs reserve
#define OVER9000 1234567890
#define ALL_THE(CAKE,LIE) for(auto LIE =CAKE.begin(); LIE != CAKE.end(); LIE++)
#define tisic 47
#define soclose 1e-8
#define chocolate win
// so much chocolate
#define patkan 9
#define ff first
#define ss second
#define abs(x) (((x) < 0)?-(x):(x))
#define uint unsigned int
#define dbl long double
#define pi 3.14159265358979323846
using namespace std;
// mylittledoge

using cat = long long;

#ifdef DONLINE_JUDGE
	// palindromic tree is better than splay tree!
	#define lld I64d
#endif

constexpr cat mod = 998244353;

cat pw(cat a, cat e) {
	if(e <= 0) return 1;
	cat x = pw(a, e/2);
	x = x * x % mod;
	if(e&1) x = x * a % mod;
	return x;
}

inline __attribute__((always_inline)) void add(const cat * __restrict A, cat * __restrict res, int L) {
	for(int i = 0; i < L; i++) {
		res[i] += A[i];
		if(res[i] >= mod) res[i] -= mod;
	}
}

inline __attribute__((always_inline)) void sub(const cat * __restrict A, cat * __restrict res, int L) {
	for(int i = 0; i < L; i++) {
		res[i] += mod-A[i];
		if(res[i] >= mod) res[i] -= mod;
	}
}

void karatsuba(const cat * __restrict A, const cat * __restrict B, cat * __restrict res, int L) {
	if(L <= 32) {
		for(int i = 0; i < L; i++) if(A[i]) for(int j = 0; j < L; j++) {
			res[i+j] += A[i] * B[j];
			constexpr cat mod2 = 4 * mod * mod;
			if(res[i+j] >= mod2) res[i+j] -= mod2;
		}
		for(int i = 0; i <= 2*L-2; i++) res[i] %= mod;
		return;
	}
	vector<cat> prod_low(2*(L/2)-1, 0), prod_high(2*(L-L/2)-1, 0);
	karatsuba(A, B, &(prod_low[0]), L/2);
	karatsuba(A+L/2, B+L/2, &(prod_high[0]), L-L/2);
	vector<cat> A_comb(L-L/2, 0), B_comb(L-L/2, 0);
	for(int i = 0; i < L/2; i++) {
		A_comb[i] = A[i] + A[i+L/2];
		if(A_comb[i] >= mod) A_comb[i] -= mod;
	}
	for(int i = 0; i < L/2; i++) {
		B_comb[i] = B[i] + B[i+L/2];
		if(B_comb[i] >= mod) B_comb[i] -= mod;
	}
	if(L%2) A_comb[L/2] = A[L-1], B_comb[L/2] = B[L-1];
	vector<cat> res_comb(2*(L-L/2)-1, 0);
	karatsuba(A_comb.data(), B_comb.data(), &(res_comb[0]), L-L/2);
	add(prod_low.data(), res, 2*(L/2)-1);
	add(prod_high.data(), res+2*(L/2), 2*(L-L/2)-1);
	sub(prod_low.data(), &(res_comb[0]), 2*(L/2)-1);
	sub(prod_high.data(), &(res_comb[0]), 2*(L-L/2)-1);
	add(res_comb.data(), res+L/2, 2*(L-L/2)-1);
}

vector<cat> multiply(vector<cat> & A, vector<cat> & B, int A_deg) {
	int N = A.size();
	vector<cat> ret(2*N-1, 0);
	if(A_deg <= 4) {
		const cat * __restrict A_ptr = A.data();
		const cat * __restrict B_ptr = B.data();
		cat * __restrict res = &(ret[0]);
		for(int i = 0; i < A_deg; i++) for(int j = 0; j < N; j++) {
			res[i+j] += A_ptr[i] * B_ptr[j];
			constexpr cat mod2 = 4 * mod * mod;
			if(res[i+j] >= mod2) res[i+j] -= mod2;
		}
		for(int i = 0; i <= 2*N-2; i++) res[i] %= mod;
	}
	else karatsuba(A.data(), B.data(), &(ret[0]), N);
	return ret;
}

int main() {
	cin.sync_with_stdio(0);
	cin.tie(0);
	cout << fixed << setprecision(10);
	int N;
	cin >> N;
	vector<int> A(N), B(N);
	cat S = 0;
	for(int i = 0; i < N; i++) {
		cin >> A[i] >> B[i];
		S += A[i];
	}
	vector<cat> fac(1000, 1), fac_inv(1000, 1);
	for(int i = 1; i < 1000; i++) {
		fac[i] = fac[i-1] * i % mod;
		fac_inv[i] = fac_inv[i-1] * pw(i, mod-2) % mod;
	}
	vector<cat> C(N);
	for(int i = 0; i < N; i++) C[i] = pw(A[i], B[i]) * fac_inv[B[i]-1] % mod;
	vector< vector<cat> > dp[2];
	dp[0] = vector< vector<cat> >(S+1, vector<cat>(404, 0)); // vector not found
	dp[1] = vector< vector<cat> >(S+1, vector<cat>(404, 0));
	dp[0][0][0] = 1;
	cat max_deg = 0;
	for(int i = 0; i < N; i++) {
		vector<cat> D(max_deg+B[i], 0);
		for(int j = 0; j < B[i]; j++) D[j] = pw(A[i], j) * fac_inv[j] % mod;
		for(int j = S-A[i]; j >= 0; j--) {
			vector<cat> prod = multiply(D, dp[1][j], B[i]);
			for(int k = 0; k < max_deg+B[i]; k++) {
				dp[1][j+A[i]][k] -= prod[k];
				if(dp[1][j+A[i]][k] < 0) dp[1][j+A[i]][k] += mod;
			}
		}
		for(int j = 0; j <= S-A[i]; j++) for(int k = 0; k <= max_deg; k++)
			dp[1][j+A[i]][k+B[i]] = (dp[1][j+A[i]][k+B[i]] + C[i] * dp[0][j][k]) % mod;
		for(int j = S-A[i]; j >= 0; j--) {
			vector<cat> prod = multiply(D, dp[0][j], B[i]);
			for(int k = 0; k < max_deg+B[i]; k++) {
				dp[0][j+A[i]][k] -= prod[k];
				if(dp[0][j+A[i]][k] < 0) dp[0][j+A[i]][k] += mod;
			}
		}
		max_deg += B[i];
	}
	cat ans = 0;
	for(int i = 1; i <= S; i++) {
		cat inv_i = pw(i, mod-2), p = 1;
		for(int j = 0; j <= max_deg; j++) {
			p = p * inv_i % mod;
			if(dp[1][i][j]) ans = (ans + dp[1][i][j] * fac[j] % mod * p) % mod;
		}
	}
	ans = ans * S % mod;
	cout << ans << "\n";
	return 0;
}

// look at my code
// my code is amazing


Measured memory_bytes: 2816