#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;   }