#include<cstdio>
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=3e5+10, mod = 998244353, G = 3, Gi = 332748118;
typedef pair<int, int> P;
ll quick(ll a,ll b,ll m)
{
ll ans=1;
while(b>0)
{
if(b&1)
ans=ans*a%m;
a=a*a%m;
b>>=1;
}
return ans;
}
ll jiecheng[maxn];
void ini_zuhelogn()
{
jiecheng[0]=1;
for(int i=1;i<maxn;i++)
{
jiecheng[i]=jiecheng[i-1]*i%mod;
}
}
ll zuhe_logn(int m,int n)
{
if(jiecheng[0]!=1)
ini_zuhelogn();
ll ans=((jiecheng[m]*quick(jiecheng[n], mod-2, mod))%mod)*quick(jiecheng[m-n], mod-2, mod)%mod;
return ans;
}
ll result_len,result[maxn],level=0,trans[maxn];
inline void NTT(ll *A, int type) {
for(int i = 0; i < result_len; i++)
if(i < trans[i]) swap(A[i], A[trans[i]]);
for(int mid = 1; mid < result_len; mid <<= 1) {
ll Wn = quick( type == 1 ? G : Gi , (mod - 1) / (mid << 1),mod);
for(int j = 0; j < result_len; j += (mid << 1)) {
ll w = 1;
for(int k = 0; k < mid; k++, w = (w * Wn) % mod) {
int x = A[j + k], y = w * A[j + k + mid] % mod;
A[j + k] = (x + y) % mod,
A[j + k + mid] = (x - y + mod) % mod;
}
}
}
}
void ntt(ll *a,int a_len,ll *b,int b_len)
{
result_len=1;level=0;
while(result_len<=a_len+b_len)
{
result_len<<=1;
level++;
}
for(int i=a_len;i<result_len;i++)
a[i]=0;
for(int i=b_len;i<result_len;i++)
b[i]=0;
for(int i=0;i<result_len;i++)
trans[i]=(trans[i>>1]>>1)|((i&1)<<(level-1));
NTT(a, 1);
NTT(b, 1);
for(int i=0;i<result_len;i++)
result[i]=(a[i]*b[i])%mod;
NTT(result,-1);
ll inv=quick(result_len, mod-2, mod);
for(int i=0;i<result_len;i++)
result[i]=(result[i]*inv)%mod;
}
P a[maxn];
vector<ll> D[maxn];
priority_queue<P> q;
ll d1[maxn],d2[maxn];
int main() {
ini_zuhelogn();
int T;
cin>>T;
while (T--) {
int n,m=0;
cin>>n;
for(int i=0;i<n;i++)
{
// cout<<i<<":"<<endl;
cin>>a[i].first>>a[i].second;
m+=a[i].first;
int t=min(a[i].first,a[i].second);
D[i].clear();
D[i].push_back(1);
for(int j=1;j<=t;j++){
D[i].push_back((zuhe_logn(a[i].first, j)*zuhe_logn(a[i].second, j))%mod*jiecheng[j]%mod);
// cout<<D[i][j]<<" ";
}
// cout<<endl;
q.push(make_pair(-t-1, i));
}
while(q.size()>1)
{
int t1=q.top().second,len1=-q.top().first;
q.pop();
int t2=q.top().second,len2=-q.top().first;
q.pop();
// cout<<t1<<" "<<len1<<": ";
for(int i=0;i<len1;i++){
d1[i]=D[t1][i];
// cout<<d1[i]<<" ";
}
// cout<<endl<<t2<<" "<<len2<<": ";
for(int i=0;i<len2;i++){
d2[i]=D[t2][i];
// cout<<d2[i]<<" ";
}
// cout<<endl;
ntt(d1, len1, d2, len2);
D[t2].clear();
for(int i=0;i<len1-1+len2;i++){
// cout<<result[i]<<" ";
D[t2].push_back(result[i]);
}
// cout<<endl;
q.push(make_pair(-len1+1-len2, t2));
}
int t=q.top().second,len=-q.top().first;
q.pop();
int flag=1;
ll ans=0;
for(int i=0;i<len;i++)
{
ans=(ans+flag*jiecheng[m-i]*D[t][i])%mod;
flag*=-1;
}
cout<<(ans+mod)%mod<<endl;
}
return 0;
}
//1
//6
//0 2
//1 0
//1 2
//0 0
//2 2
//2 0