#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define pb push_back
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define mem(a) memset(a, 0, sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef double db;
typedef __int128_t int128;
const int maxn = 4 * 1e5 + 10, P = 998244353, G = 3, Gi = 332748118;
const ll mod = P;
//Gi是原根的逆元
int limit = 1, L, rev[maxn];
vector<ll> a, b;
ll fac[maxn], inv[maxn];
int n;
ll in[maxn], de[maxn];
vector<ll> tmp;
inline ll qp(ll a, ll k, ll mod = P)
{
    ll base = 1;
    while (k)
    {
        if (k & 1)
            base = (base * a) % mod;
        a = (a * a) % mod;
        k >>= 1;
    }
    return base % mod;
}
int cnt = 0;
inline void NTT(vector<ll> &A, int type)
{
    //cout << "SSSSS" << cnt++ << endl;
    for (int i = 0; i < limit; i++)
        if (i < rev[i])
            swap(A[i], A[rev[i]]);
    for (int mid = 1; mid < limit; mid <<= 1)
    {
        ll Wn = qp(type == 1 ? G : Gi, (P - 1) / (mid << 1));
        for (int j = 0; j < limit; j += (mid << 1))
        {
            ll w = 1;
            for (int k = 0; k < mid; k++, w = (w * Wn) % P)
            {
                //cout << mid << " " << j << " " << k << endl;
                int x = A[j + k], y = w * A[j + k + mid] % P;
                A[j + k] = (x + y) % P, A[j + k + mid] = (x - y + P) % P;
            }
        }
    }
    if (type == -1)
    {
        ll inv = qp(limit, P - 2);
        for (int i = 0; i < limit; i++)
            A[i] = A[i] * inv % P;
    }
}
void init(int N, int M)
{
    limit = 1;
    L = 0;
    while (limit <= N + M)
        limit <<= 1, L++;
    for (int i = 0; i < limit; i++)
    {
        rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (L - 1));
    }
}
void I()
{
    fac[0] = 1, inv[0] = 1;
    for (int i = 1; i < maxn; i++)
        fac[i] = fac[i - 1] * i % P, inv[i] = qp(fac[i], mod - 2);
}
ll C(int n, int k)
{
    if (k < 0 || k > n)
        return 0;
    return 1ll * fac[n] * inv[k] % mod * inv[n - k] % mod;
}
void mul(vector<ll> &a, vector<ll> &b)
{
    int n = a.size(), m = b.size();
    init(n, m);
    a.resize(limit), b.resize(limit);
    //cout << limit << endl;
    NTT(a, 1), NTT(b, 1);
    for (int i = 0; i < limit; i++)
        a[i] = a[i] * b[i] % mod;
    NTT(a, -1);
}
int main()
{
    I();
    //cout << C(6, 3) << " " << C(6, 2) << endl;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> in[i] >> de[i];
    a.pb(1);
    int len = 1;
    for (int i = 1; i <= n; i++)
    {
        //cout << "I= " << i << endl;
        len += in[i] - de[i];
        tmp.clear();
        int prev = a.size();
        for (int j = de[i] - prev + 1; j <= prev + in[i] - 1; j++)
        {
            tmp.pb(C(in[i] + de[i], j));
        }
        mul(tmp, a);
        vector<ll> tmp2(len,0);
        for (int i = 0; i < len; i++)
            tmp2[i]=(tmp[i + prev - 1]);
        a.clear();
        a = tmp2;
    }
    ll ans = 0;
    for (auto c : a)
    {
        //cout << c << endl;
        ans = (ans + c) % mod;
    }
    cout << ans << endl;
    return 0;
}