/**
HDU 6273 Master of GCD 分块
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6273
题意:给定长度为n初始值为1的数组,给定m操作l r v,表示区间[l,r]乘以v
ans: 更新后数组的最大公约数;
分析:分块 打标记,对于每个位置 ,记录每个位置2,3的个数;
最后线性扫一遍即可;
*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
const ll mod=998244353;
const int maxn=1e5+7;
int blo,pos[maxn],s2[maxn],s3[maxn],tag2[maxn],tag3[maxn];
void pushdown(int x){
if(tag2[x]==0&&tag3[x]==0) return ;
for(int i=(x-1)*blo+1;i<=x*blo;i++) {
s2[i]+=tag2[x];
s3[i]+=tag3[x];
}
tag2[x]=0,tag3[x]=0;
}
void update(int l,int r,int x){
for(int i=pos[l]+1;i<=pos[r]-1;i++) {
if(x==3) tag3[i]++;
else tag2[i]++;
}
if(pos[l]!=pos[r]){
pushdown(pos[l]),pushdown(pos[r]);
for(int i=l;i<=pos[l]*blo;i++) {
if(x==2) s2[i]++;
else s3[i]++;
}
for(int i=(pos[r]-1)*blo+1;i<=r;i++){
if(x==2) s2[i]++;
else s3[i]++;
}
}
else {
pushdown(pos[l]);
for(int i=l;i<=r;i++){
if(x==2) s2[i]++;
else s3[i]++;
}
}
}
ll ksm(ll a,ll b){
ll ans=1;
while(b){
if(b&1) ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans;
}
int main(){
int t;scanf("%d",&t);
while(t--){
int n,m;scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++) s2[i]=s3[i]=tag2[i]=tag3[i]=0;
blo=(int)sqrt(n*1.0);
for(int i=1;i<=n;i++) pos[i]=(i-1)/blo+1;
while(m--){
int l,r,v;scanf("%d %d %d",&l,&r,&v);
update(l,r,v);
}
int l=1e7+7,r=1e7+7;
for(int i=1;i<=n;i++){
s2[i]+=tag2[pos[i]];
s3[i]+=tag3[pos[i]];
}
for(int i=1;i<=n;i++){
l=min(s2[i],l);
r=min(s3[i],r);
}
ll ans=ksm(2ll,l);
ans=ans*ksm(3ll,r)%mod;
printf("%lld\n",ans);
}
return 0;
}