#include <bits/stdc++.h>
using namespace std;

namespace NTT
{
    const int P=998244353,g=3;
    const int W=22,S=1<<W;
    const int J=86583718;

    inline int add(int a,int b) {int r=a+b; return r<P?r:r-P;}
    inline int sub(int a,int b) {int r=a-b; return r<0?r+P:r;}
    inline int mul(long long a,long long b) {return (a*b)%P;}
    inline int inv(int a) {return a==1?a:mul(inv(P%a),P-P/a);}
    inline int qpow(int a,long long k)
    {
        int r=1;
        while (k)
        {
            if (k&1) r=mul(r,a);
            k>>=1; a=mul(a,a);
        }
        return r;
    }

    int r[S],w[2][S];
    void init(int lim)
    {
        int w0=qpow(g,(P-1)/lim);
        w[0][0]=w[1][0]=1;
        for (int i=1;i<lim;i++) w[0][i]=w[1][lim-i]=mul(w[0][i-1],w0);
        for (int i=0;i<lim;i++) r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));
    }

    void ntt(int *a,int lim,int o)
    {
        for (int i=0;i<lim;i++) if (i<r[i]) swap(a[i],a[r[i]]);
        for (int i=1;i<lim;i<<=1)
        {
            for (int j=0,t=lim/(i<<1);j<lim;j+=i<<1)
            {
                for (int k=j,l=0;k<j+i;k++,l+=t)
                {
                    int x=a[k],y=mul(w[o][l],a[k+i]);
                    a[k]=add(x,y);
                    a[k+i]=sub(x,y);
                }
            }
        }
        if (o)
        {
            int tmp=NTT::inv(lim);
            for (int i=0;i<lim;i++) a[i]=mul(a[i],tmp);
        }
    }

    vector<int> poly_add(const vector<int> &a,const vector<int> &b)
    {
        int n=a.size(),m=b.size();
        vector<int> c;
        for (int i=0;i<max(n,m);i++) c.push_back(add((i<n?a[i]:0),(i<m?b[i]:0)));
        return c;
    }

    vector<int> poly_sub(const vector<int> &a,const vector<int> &b)
    {
        int n=a.size(),m=b.size();
        vector<int> c;
        for (int i=0;i<max(n,m);i++) c.push_back(sub((i<n?a[i]:0),(i<m?b[i]:0)));
        return c;
    }

    vector<int> poly_d(const vector<int> &a)
    {
        int n=a.size();
        vector<int> b;
        for (int i=1;i<n;i++) b.push_back(mul(a[i],i));
        return b;
    }

    vector<int> poly_s(const vector<int> &a)
    {
        int n=a.size();
        vector<int> b{0};
        for (int i=0;i<n;i++) b.push_back(mul(a[i],inv(i+1)));
        return b;
    }

    int p1[S],p2[S];
    vector<int> poly_mul(const vector<int> &a,const vector<int> &b)
    {
        int n=a.size(),m=b.size();
        int lim=1;
        while (lim<(n<<1)) lim<<=1;
        while (lim<(m<<1)) lim<<=1;
        init(lim);
        for (int i=0;i<lim;i++) r[i]=(i&1)*(lim>>1)+(r[i>>1]>>1);
        copy_n(a.begin(),n,p1); fill(p1+n,p1+lim,0);
        copy_n(b.begin(),m,p2); fill(p2+m,p2+lim,0);
        ntt(p1,lim,0);
        ntt(p2,lim,0);
        for (int i=0;i<lim;i++) p1[i]=mul(p1[i],p2[i]);
        ntt(p1,lim,1);
        return vector<int>(p1,p1+n+m-1);
    }

    vector<int> poly_inv(const vector<int> &a)
    {
        int n=a.size();
        if (n==1) return {inv(a[0])};
        auto b=a; b.resize((n+1)>>1);
        b=poly_inv(b);
        int m=b.size();
        int lim=1;
        while (lim<(n<<1)) lim<<=1;
        while (lim<(m<<1)) lim<<=1;
        init(lim);
        copy_n(a.begin(),n,p1); fill(p1+n,p1+lim,0);
        copy_n(b.begin(),m,p2); fill(p2+m,p2+lim,0);
        ntt(p1,lim,1);
        ntt(p2,lim,1);
        for (int i=0;i<lim;i++) p1[i]=mul(p2[i],sub(2,mul(p1[i],p2[i])));
        ntt(p1,lim,-1);
        return vector<int>(p1,p1+n);
    }

    vector<int> poly_div(const vector<int> &a,const vector<int> &b)
    {
        int n=a.size(),m=b.size();
        if (m>n) return {0};
        auto ar=a,br=b;
        reverse(ar.begin(),ar.end()); reverse(br.begin(),br.end());
        ar.resize(n-m+1); br.resize(n-m+1);
        br=poly_inv(br);
        auto q=poly_mul(ar,br); q.resize(n-m+1);
        reverse(q.begin(),q.end());
        return q;
    }

    vector<int> poly_mod(const vector<int> &a,const vector<int> &b)
    {
        int m=b.size();
        auto c=poly_div(a,b);
        c=poly_mul(b,c);
        c=poly_sub(a,c); c.resize(m-1);
        return c;
    }

    vector<int> poly_sqrt(const vector<int> &a)
    {
        int n=a.size();
        if (n==1) return {1};
        auto b=a; b.resize((n+1)>>1);
        b=poly_sqrt(b); b.resize(n);
        auto c=poly_add(b,poly_mul(poly_inv(b),a)); c.resize(n);
        int i2=inv(2); for (int &i:c) i=mul(i,i2);
        return c;
    }

    vector<int> poly_ln(const vector<int> &a)
    {
        int n=a.size();
        auto b=poly_mul(poly_inv(a),poly_d(a));
        b.resize(n-1); b=poly_s(b);
        return b;
    }

    vector<int> poly_exp(const vector<int> &a)
    {
        int n=a.size();
        if (n==1) return {1};
        auto b=a; b.resize((n+1)>>1);
        b=poly_exp(b); b.resize(n);
        auto c=poly_sub(a,poly_ln(b)); c[0]=add(c[0],1);
        c=poly_mul(b,c); c.resize(n);
        return c;
    }

    vector<int> poly_sin(const vector<int> &a)
    {
        auto b=a;
        for (int &i:b) i=mul(i,J);
        auto c=poly_exp(b);
        c=poly_sub(c,poly_inv(c));
        int i2=inv(2),ij=inv(J);
        for (int &i:c) i=mul(i,mul(i2,ij));
        return c;
    }

    vector<int> poly_cos(const vector<int> &a)
    {
        auto b=a;
        for (int &i:b) i=mul(i,J);
        auto c=poly_exp(b);
        c=poly_add(c,poly_inv(c));
        int i2=inv(2);
        for (int &i:c) i=mul(i,i2);
        return c;
    }

    vector<int> poly_asin(const vector<int> &a)
    {
        int n=a.size();
        auto b=poly_d(a),c=poly_mul(a,a); c.resize(n);
        c=poly_inv(poly_sqrt(poly_sub({1},c)));
        b=poly_mul(b,c); b.resize(n-1);
        return poly_s(b);
    }

    vector<int> poly_atan(const vector<int> &a)
    {
        int n=a.size();
        auto b=poly_d(a),c=poly_mul(a,a); c.resize(n);
        c=poly_inv(poly_add({1},c));
        b=poly_mul(b,c); b.resize(n-1);
        return poly_s(b);
    }
}

const int N=200010;

int n,a,b;
long long inv[N];
long long fac[N],invf[N];

void linear_inv(long long n,long long p)
{
    inv[1]=1;
    for (long long i=2;i<=n;i++) inv[i]=(p-p/i)*inv[p%i]%p;
    fac[0]=1;
    for (long long i=1;i<=n;i++) fac[i]=fac[i-1]*i%p;
    invf[n]=NTT::inv(fac[n]);
    for (long long i=n-1;i>=0;i--) invf[i]=invf[i+1]*(i+1)%p;
}

long long C(long long n,long long m)
{
    if (m>n) return 0;
    return NTT::mul(fac[n],NTT::mul(invf[m],invf[n-m]));
}

int main()
{
    linear_inv(200000,NTT::P);
    scanf("%d",&n);
    vector<int> ans={1};
    int l=1;
    for (int i=1;i<=n;i++)
    {
        scanf("%d%d",&a,&b);
        vector<int> f;
        int sz=min(l+l+a-b-1,a+b+1);
        for (int j=(a+b+1-sz)/2;j<=a+b-(a+b+1-sz)/2;j++)
        {
            f.push_back(C(a+b,j));
        }
        ans=NTT::poly_mul(ans,f);
        l+=a-b;
        int now=ans.size();
        ans.erase(ans.begin(),ans.begin()+(now-l)/2);
        ans.erase(ans.end()-(now-l)/2,ans.end());
    }
    int sum=0;
    for (int i:ans)
    {
        sum=NTT::add(sum,i);
    }
    printf("%d",sum);
    getchar(); getchar();
    return 0;
}