rt,WA*33
#include<bits/stdc++.h>
#include<atcoder/math>
#define ll long long
#define ull unsigned long long
#define ld long double
#define rep(i,l,r) for(register ll i=(l);i<=(r);++i)
#define Rep(i,l,r) for(register ll i=(r);i>=(l);--i)
#define all(x) x.begin(),x.end()
#define Set(x,y) memset(x,y,sizeof(x))
#define Cpy(x,y) memcpy(x,y,sizeof(x))
#define cll const long long
using namespace std;
template<class T>
void death(T s){cout<<s<<endl;exit(0);}
cll N=200009;
struct Line{
ld b,k; ll id;
ld val(ld u){return k*u+b;}
bool operator<(const Line&x)const{return k>x.k;}
#define b(u) lines[u].b
#define k(u) lines[u].k
}lines[N];
struct HalfPlane{ll a,b,c;} p[N];//ax+by<=c
ld X(ll u,ll v){
return -(ld)(b(u)-b(v))/(k(u)-k(v));
}
ll n,q[N];
const ll MOD=998244353;
void clr(){
rep(i,0,n){
lines[i]=(Line){0,0};
p[i]=(HalfPlane){0,0,0};
q[i]=0;
}
n=0;
}
void solve(){
cin>>n;
rep(i,1,n){
ll a,b,c;
cin>>a>>b>>c;
c--;
lines[i]=(Line){1.*c/b,-1.*a/b,i};
p[i]=(HalfPlane){a,b,c};
}
sort(lines+1,lines+1+n);
ll l=1,r=1;
rep(i,1,n){
while(r-l>=2&&X(i,q[r-1])<X(q[r-1],q[r-2])) r--;
q[r++]=i;
}
ll ans=0,x0=1;
for(;r>l;++l){
ll id=lines[q[l]].id;
ll x0=1,x1=X(q[l],0);
if(l!=1){
ld a=X(q[l],q[l-1]);
if(floor(a)==a)x0=a+1;
else x0=ceil(a);
}
if(r-l!=1){
ld a=X(q[l],q[l+1]);
x1=floor(a);
}
x0=max(x0,1ll);
x1=min(x1,(ll)floor(X(q[l],0)));
if(x1<x0)continue;
ll a=p[id].a,b=p[id].b,c=p[id].c;
(ans+=atcoder::floor_sum(x1-x0+1,b,-a,c-a*x0))%=MOD;
}
cout<<ans<<endl;
}
int main(){
ll T;
cin>>T;
while(T--){
clr();
solve();
}
return 0;
}
(悬一关)