Problem:
J Proper Instructions
問題文
umgくんは $1$ 次元上の座標 $0$ にいます。今は時刻 $0$ です。時刻が $1$ 進むごとに、今いる座標より $1$ 大きい座標に移動するか、 $1$ 小さい座標に移動するか、その座標にとどまるかという行動ができます。
$N$ 個の指示が与えられます。 $i$ 個目の指示は、「時刻 $T_i$ には $L_i\leq x \leq R_i$ を満たす座標 $x$ にいなければならない」という指示です。
$N$個の指示の空でない部分集合 $S$ が「適切」であるとは、umgくんが上手く動くことで、 $S$ に含まれるすべての指示に従うことができることをいいます。
適切である指示の集合としてあり得るものの個数を求めてください。ただし、 $2$ つの指示の集合が異なるとは、一方には含まれるが他方には含まれない指示が存在することをいいます。答えは非常に大きくなることがあるので、 $998244353$ で割った余りを求めてください。
入力
入力は以下の形式で標準入力から与えられる。
$N$
$T_1$ $L_1$ $R_1$
$T_2$ $L_2$ $R_2$
$\vdots$
$T_N$ $L_N$ $R_N$
制約
入力はすべて整数である。
$1 \leq N \leq 300$
$1 \leq T_1 \lt T_2 \lt \cdots \lt T_N \leq 10^9$
$-10^9 \leq L_i \leq R_i \leq 10^9$
出力
答えを 1 行に出力せよ。
入力例1
3
1 0 2
2 -4 -2
4 2 10
出力例1
4
適切な指示の集合は $\{1\},\{2\},\{3\},\{1,3\}$ の4つです。
入力例2
3
1 100 200
40 100 200
60 100 200
出力例2
0
umgくんはどう頑張ってもいずれの指示も達成することができません。
入力例3
9
6 -64 84
7 39 99
37 -53 64
42 19 32
46 -86 -37
79 57 64
85 -96 -31
87 -10 79
91 -80 86
出力例3
95

Submitted solutions:

code_snippet: // AOJ #3181 Proper Instructions
// 2025.4.7

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 998244353;

struct Instr { ll t, L, R; };

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int n;
    cin >> n;
    vector<Instr> a(n);
    for(int i=0; i<n; i++) cin >> a[i].t >> a[i].L >> a[i].R;

    vector<map<pair<ll,ll>, ll>> dp(n);
    ll ans = 0;
    for (int i = 0; i < n; i++){
        ll lo = max(a[i].L, -a[i].t);
        ll hi = min(a[i].R, a[i].t);
        if(lo <= hi)  dp[i][{lo, hi}] = (dp[i][{lo, hi}] + 1) % MOD;
        for (int j = 0; j < i; j++){
            ll d = a[i].t - a[j].t;
            for(auto &st : dp[j]){
                ll l = st.first.first, r = st.first.second;
                ll cnt = st.second;
                ll nl = max(a[i].L, l - d);
                ll nh = min(a[i].R, r + d);
                if(nl <= nh) dp[i][{nl, nh}] = (dp[i][{nl, nh}] + cnt) % MOD;
            }
        }
        for(auto &st: dp[i]) ans = (ans + st.second) % MOD;
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 310
memory_kb: 11680
final_rank: 7

code_snippet: //#define _GLIBCXX_DEBUG

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

#define endl '\n'
#define lfs cout<<fixed<<setprecision(10)
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define spa << " " <<
#define fi first
#define se second
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = (n); i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
using ll = long long;
using ld = long double;
const ll MOD1 = 1e9+7;
const ll MOD9 = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T1, typename T2>bool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;}
template<typename T1, typename T2>bool chmax(T1 &a,T2 b){if(a<b){a=b;return true;}else return false;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}  
template<typename T>void debug(vector<vector<T>>&v,ll h,ll w){for(ll i=0;i<h;i++){cout<<v[i][0];for(ll j=1;j<w;j++)cout spa v[i][j];cout<<endl;}};
void debug(vector<string>&v,ll h,ll w){for(ll i=0;i<h;i++){for(ll j=0;j<w;j++)cout<<v[i][j];cout<<endl;}};
template<typename T>void debug(vector<T>&v,ll n){if(n!=0)cout<<v[0];for(ll i=1;i<n;i++)cout spa v[i];cout<<endl;};
template<typename T>vector<vector<T>>vec(ll x, ll y, T w){vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
vector<ll>dx={1,-1,0,0,1,1,-1,-1};vector<ll>dy={0,0,1,-1,1,-1,1,-1};
template<typename T>vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
template<typename... Ts>auto make_v(size_t a,Ts... ts){return vector<decltype(make_v(ts...))>(a,make_v(ts...));}
template<typename T1, typename T2>ostream &operator<<(ostream &os, const pair<T1, T2>&p){return os << p.first << " " << p.second;}
template<typename T>ostream &operator<<(ostream &os, const vector<T> &v){for(auto &z:v)os << z << " ";cout<<"|"; return os;}
//mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
template< int mod >
struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  friend ModInt operator+(const ModInt& lhs, const ModInt& rhs) {
        return ModInt(lhs) += rhs;
  }
  friend ModInt operator-(const ModInt& lhs, const ModInt& rhs) {
        return ModInt(lhs) -= rhs;
  }
  friend ModInt operator*(const ModInt& lhs, const ModInt& rhs) {
        return ModInt(lhs) *= rhs;
  }
  friend ModInt operator/(const ModInt& lhs, const ModInt& rhs) {
        return ModInt(lhs) /= rhs;
  }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }

  static int get_mod() { return mod; }
};
using modint = ModInt< MOD9 >;modint pow(ll n, ll x){return modint(n).pow(x);}modint pow(modint n, ll x){return n.pow(x);}
//using modint=ld;
int main(){
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  ll res=0,buf=0;
  bool judge = true;
  ll n;cin>>n;
  vector<ll>t(n+1),l(n+1),r(n+1);
  rep(i,1,n+1)cin>>t[i]>>l[i]>>r[i];
  auto dp=vec(n+1,n+1,modint(0));
  dp[0][0]=1;
  rep(i,1,n+1){
    auto ndp=vec(n+1,n+1,modint(0));
    rep(j,0,i)rep(o,0,i){
      ndp[j][o]+=dp[j][o];
      ll nl=l[j]-(t[i]-t[j]);
      ll nr=r[o]+(t[i]-t[o]);
      if(nr<l[i]||r[i]<nl)continue;
      ll tx=j,ty=o;
      if(nl<l[i])tx=i;
      if(nr>r[i])ty=i;
      ndp[tx][ty]+=dp[j][o];
    }
    dp.swap(ndp);
    //debug(dp,n+1,n+1);cout<<endl;
  }
  modint ret=0;
  rep(i,0,n+1)rep(j,0,n+1)ret+=dp[i][j];
  cout<<ret-1<<endl;
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3700
final_rank: 2

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

#define rep(i, m, n) for(int(i) = (int)(m); i < (int)(n); ++i)
#define rep2(i, m, n) for(int(i) = (int)(n)-1; i >= (int)(m); --i)
#define REP(i, n) rep(i, 0, n)
#define REP2(i, n) rep2(i, 0, n)
#define all(hoge) (hoge).begin(), (hoge).end()
#define en '\n'
using ll = long long;
using ull = unsigned long long;
template <class T>
using vec = vector<T>;
template <class T>
using vvec = vector<vec<T>>;
typedef pair<ll, ll> P;
using tp = tuple<ll, ll, ll>;
constexpr long long INF = 1LL << 60;
constexpr int INF_INT = 1 << 25;
//constexpr long long MOD = (ll)1e9 + 7;
constexpr long long MOD = 998244353LL;
using ld = long double;
static const ld pi = 3.141592653589793L;
typedef vector<ll> Array;
typedef vector<Array> Matrix;

template <class T>
inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

//グラフ関連
struct Edge {
    ll to, cap, rev;
    Edge(ll _to, ll _cap, ll _rev) {
        to = _to;
        cap = _cap;
        rev = _rev;
    }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

void add_edge(Graph &G, ll from, ll to, ll cap, bool revFlag, ll revCap) {
    G[from].push_back(Edge(to, cap, (ll)G[to].size()));
    if(revFlag)
        G[to].push_back(Edge(from, revCap, (ll)G[from].size() - 1));
}
void solve() {
    ll n;
    cin >> n;
    vec<ll> t(n + 1, 0), l(n + 1, 0), r(n + 1, 0);
    rep(i, 1, n + 1) {
        cin >> t[i] >> l[i] >> r[i];
    }

    priority_queue<tp, vec<tp>, greater<tp>> que;
    que.push({0, 0, 0});
    map<tp, ll> mp;
    mp[{0, 0, 0}] = 1;
    ll ans = 0;
    while(que.size()) {
        auto [i, pl, pr] = que.top();
        que.pop();
        //cout << i << " " << pl << " " << pr << en;
        ll tmp = mp[{i, pl, pr}];
        (ans += tmp) %= MOD;
        rep(j, i + 1, n + 1) {
            ll d = t[j] - t[i];
            ll nl = max(pl - d, l[j]);
            ll nr = min(pr + d, r[j]);
            //cout << i << " " << j << " " << nl << " " << nr << en;
            if(nl > nr)
                continue;
            if(!mp.count({j, nl, nr}))
                que.push({j, nl, nr});
            (mp[{j, nl, nr}] += tmp) %= MOD;
        }
    }
    ans += MOD - 1;
    ans %= MOD;
    cout << ans << en;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    /*
    ll t;
    cin >> t;
    while(t--)*/
    solve();

    return 0;
}
accuracy: 1
time_ms: 910
memory_kb: 14440
final_rank: 10

code_snippet: #include <bits/stdc++.h>
//#include <chrono>
//#pragma GCC optimize("Ofast")
using namespace std;
#define reps(i,s,n) for(int i = s; i < n; i++)
#define rep(i,n) reps(i,0,n)
#define Rreps(i,n,e) for(int i = n - 1; i >= e; --i)
#define Rrep(i,n) Rreps(i,n,0)
#define ALL(a) a.begin(), a.end()
#define fi first
#define se second

using ll = long long;
using vec = vector<ll>;
using mat = vector<vec>;

ll N,M,H,W,Q,K,A,B;
string S;
typedef pair<ll, ll> P;
const ll INF = (1LL<<58);

template <unsigned long long mod > class modint{
public:
    ll x;
    constexpr modint(){x = 0;}
    constexpr modint(ll _x) : x((_x < 0 ? ((_x += (LLONG_MAX / mod) * mod) < 0 ? _x + (LLONG_MAX / mod) * mod : _x) : _x)%mod){}
    constexpr void set_raw(ll _x){
        //_x in [0, mod)
        x = _x;
    }
    constexpr modint operator-(){
        return x == 0 ? 0 : mod - x;
    }
    constexpr modint& operator+=(const modint& a){
        if((x += a.x) >= mod) x -= mod;
        return *this;
    }
    constexpr modint operator+(const modint& a) const{
        return modint(*this) += a;
    }
    constexpr modint& operator-=(const modint& a){
        if((x -= a.x) < 0) x += mod;
        return *this;
    }
    constexpr modint operator-(const modint& a) const{
        return modint(*this) -= a;
    }
    constexpr modint& operator*=(const modint& a){
        (x *= a.x)%=mod;
        return *this;
    }
    constexpr modint operator*(const modint& a) const{
        return modint(*this) *= a;
    }
    constexpr modint pow(unsigned long long pw) const{
        modint res(1), comp(*this);
        while(pw){
            if(pw&1) res *= comp;
            comp *= comp;
            pw >>= 1;
        }
        return res;
    }
    //以下、modが素数のときのみ
    constexpr modint inv() const{
        return modint(*this).pow(mod - 2);
    }
    constexpr modint& operator/=(const modint &a){
        (x *= a.inv().x)%=mod;
        return *this;
    }
    constexpr modint operator/(const modint &a) const{
        return modint(*this) /= a;
    }
};
#define mod1 998244353
using mint = modint<mod1>;

ostream& operator<<(ostream& os, const mint& a){
    os << a.x;
    return os;
}
using vm = vector<mint>;

int main() {
    cin>>N;
    vec t(N + 1), l(N + 1), r(N + 1);
    t[0] = l[0] = r[0] = 0;
    reps(i, 1, N + 1) cin>>t[i]>>l[i]>>r[i];
    vector<vm> dp(N + 1, vm(N + 1, 0));
    dp[0][0] = 1;
    struct query{ int j, k; mint a; query(int _j, int _k, mint _a) : j(_j), k(_k), a(_a) {}};
    reps(i, 1, N + 1){
        queue<query> que;
        rep(j, i){
            rep(k, i){
                if(dp[j][k].x != 0 && r[i] >= l[j] - (t[i] - t[j]) && l[i] <= r[k] + (t[i] - t[k])){
                    que.emplace(l[i] <= l[j] - (t[i] - t[j]) ? j : i, r[k] + (t[i] - t[k]) <= r[i] ? k : i, dp[j][k]);
                }
            }
        }
        while(!que.empty()){
            query q = que.front(); que.pop();
            dp[q.j][q.k] += q.a;
        }
    }
    mint res(0);
    rep(i, N + 1) res += accumulate(ALL(dp[i]), mint(0));
    cout<<res - 1<<endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3856
final_rank: 1

code_snippet: // #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region aliases

#define rep(i, n) for(long long i = 0; i < (n); i++)
#define rrep(i, n) for(long long i = (n)-1; i > -1; i--)
#define Rep(i, m, n) for(long long i = (m); i < (n); i++)
#define rRep(i, m, n) for(long long i = (n)-1; i >= (m); i--)
#define REP(i, m, n, p) for(long long i = m; i < n; i += p)
#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define bcnt(n) __builtin_popcountll(n)
#define endk endl
#define ednl endl
#define enld endl

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vb = vector<bool>;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using mll = map<long long, long long>;
using pll = pair<long long, long long>;
using qll = queue<long long>;
using sll = set<long long>;
using vpll = vector<pair<long long, long long>>;
template <class T = ll>
using V = vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
//昇順pq(小さい方から取り出す)
template <class T = ll>
using pqup = priority_queue<T, vector<T>, greater<T>>;
//降順pq(大きい方から取り出す)
template <class T = ll>
using pqdn = priority_queue<T>;

#pragma endregion

#pragma region constants

long long const limLL = 9223372036854775807;  // POW(2,63)-1 ~ 9.22e18
long long const dekai = 3e16;
const long double pi = acos(-1);
const char dl = '\n';
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
int ddx[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int ddy[8] = {-1, 0, 1, -1, 1, -1, 0, 1};

// const int mod = 1000000007;
const int mod = 998244353;

#pragma endregion

#pragma region basic_procedure

template <class T>
inline bool isin(T x, T lef, T rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { cout << (f ? "Yes" : "No") << "\n"; }
void No() { cout << "No\n"; }
void YES(bool f = 1) { cout << (f ? "YES" : "NO") << "\n"; }
void NO() { cout << "NO\n"; }
template <class T>
void drop(T answer) {
	cout << answer << "\n";
	exit(0);
}
void err() {
	cout << -1 << "\n";
	exit(0);
}

template <class T>
void vout(vector<T> &v, bool tate = 0) {
	if(v.size() > 0) {
		for(auto it = v.begin(); it < v.end(); it++) {
			cout << *it;
			if(it != v.end() - 1) {
				if(tate)
					cout << endl;
				else
					cout << " ";
			}
		}
	}
	cout << endl;
}

template <class T>
void add(vector<T> &v, T val) {	 //ベクトルの各要素に加算
	for(auto &a : v) a += val;
	return;
}

// vectorの中身を数える map<要素,個数>を返す
template <class T>
map<T, long long> cntv(vector<T> v) {
	map<T, long long> m;
	for(auto &g : v) {
		if(m.count(g))
			m[g]++;
		else
			m[g] = 1;
	}
	return m;
}

//配列圧縮
//{1,36,1,3,8,-2,-92}を
//{2, 5,2,3,4, 1,  0}にする
template <class T>
vector<long long> press(vector<T> &v) {
	long long n = v.size();
	vector<long long> w(n);
	map<T, long long> m;
	for(T &p : v) m[p] = 0;
	long long i = 0;
	for(auto &p : m) {
		p.second = i;
		i++;
	}
	for(long long i = 0; i < n; i++) w.at(i) = m[v.at(i)];
	return w;
}

// 切り上げ除算
template <class T>
T dup(T a, T b) {
	assert(b != 0);
	T x = abs(a);
	T y = abs(b);
	T z = (x + y - 1) / y;
	if((a < 0 && b > 0) || (a > 0 && b < 0))
		return -z;
	else if(a == 0)
		return 0;
	else
		return z;
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	if(mod == 1) return 0LL;
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res;
}

// a * x % mod == __gcd(a,mod)なるxを返す
// a が modの倍数でないことが条件
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		swap(a, b);
		u -= t * v;
		swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

vvll comb(100, vll(100, -1));
long long com(long long n, long long k) {  //普通の二項計数(overflowに注意)
	assert(n < 100 && k < 100);
	if(n < k || k < 0 || n < 0) return 0;
	if(comb[n][k] != -1) return comb[n][k];
	ll res;
	if(n - k < k)
		res = com(n, n - k);
	else if(k == 0)
		res = 1;
	else
		res = com(n - 1, k - 1) + com(n - 1, k);
	comb[n][k] = res;
	return res;
}

// nCk modを求める
const int MAX = 5100000;
// この値は求める二項計数の値に応じて変える
// MAX=3*10^7のとき1900msほど、ほぼ比例
// MAX=5*10^6程度ならそれほど気にしなくてよい(300ms程)
long long fac[MAX], finv[MAX], inv[MAX];

void cominit() {
	// テーブルを作る前処理
	fac[0] = fac[1] = 1;
	finv[0] = finv[1] = 1;
	inv[1] = 1;
	for(int i = 2; i < MAX; i++) {
		fac[i] = fac[i - 1] * i % mod;
		inv[i] = mod - inv[mod % i] * (mod / i) % mod;
		finv[i] = finv[i - 1] * inv[i] % mod;
	}
}
long long commod(long long n, long long k) {  // 二項係数
	if(n < k) return 0;
	if(n < 0 || k < 0) return 0;
	return fac[n] * (finv[k] * finv[n - k] % mod) % mod;
}
long long pmod(long long n, long long k) {	// 順列
	if(n < k) return 0;
	if(n < 0 || k < 0) return 0;
	return fac[n] * finv[n - k] % mod;
}
// n個の区別しないボールを区別するk個の箱に入れる方法の総数
long long hmod(long long n, long long k) {	// 重複組み合わせ
	return commod(n + k - 1, n);
}
#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define CHAR(...)     \
	char __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define DOUBLE(...)     \
	double __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	INPUT(__VA_ARGS__)

template <class T>
void scan(T &a) {
	cin >> a;
}
template <class T>
void scan(vector<T> &a) {
	for(auto &i : a) scan(i);
}
template <class T, class L>
void scan(pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}
void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
template <class T>
inline void print(T x) {
	cout << x << '\n';
}

template <typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	cerr << ", ";
	view(p.second);
	cerr << ")";
}

template <typename T>
void view(std::set<T> &s) {
	if(s.empty()) {
		cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << "\n";
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		cerr << ", ";
		view(c.second);
		cerr << ")\n";
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		cerr << "] : ";
		view(t.second);
		cerr << "\n";
	}
	std::cerr << "}";
}

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	view(H);
	cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                           \
	do {                                                     \
		cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                              \
		cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                 \
	do {                                        \
		cerr << __LINE__ << " " << #x << " : "; \
		view(x);                                \
		cerr << "\n";                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region modint

template <int mod>
struct ModInt {
	int x;
	ModInt() : x(0) {}
	ModInt(long long y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
	ModInt &operator+=(const ModInt &p) {
		if((x += p.x) >= mod) x -= mod;
		return *this;
	}
	ModInt &operator-=(const ModInt &p) {
		if((x += mod - p.x) >= mod) x -= mod;
		return *this;
	}
	ModInt &operator*=(const ModInt &p) {
		x = (int)(1LL * x * p.x % mod);
		return *this;
	}
	ModInt &operator/=(const ModInt &p) {
		*this *= p.inverse();
		return *this;
	}
	ModInt operator-() const { return ModInt(-x); }
	ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
	ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
	ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
	ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
	bool operator==(const ModInt &p) const { return x == p.x; }
	bool operator!=(const ModInt &p) const { return x != p.x; }
	ModInt inverse() const {
		int a = x, b = mod, u = 1, v = 0, t;
		while(b > 0) {
			t = a / b;
			swap(a -= t * b, b);
			swap(u -= t * v, v);
		}
		return ModInt(u);
	}
	ModInt pow(long long n) const {
		ModInt ret(1), mul(x);
		while(n > 0) {
			if(n & 1) ret *= mul;
			mul *= mul;
			n >>= 1;
		}
		return ret;
	}
	friend ostream &operator<<(ostream &os, const ModInt &p) { return os << p.x; }
	friend istream &operator>>(istream &is, ModInt &a) {
		long long t;
		is >> t;
		a = ModInt<mod>(t);
		return (is);
	}
	static int get_mod() { return mod; }
};
using mint = ModInt<mod>;

#pragma endregion

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout << fixed << setprecision(15);
	srand((unsigned)time(NULL));

	INT(n);
	vector<int> t(n + 1), l(n + 1), r(n + 1);
	rep(i, n) { cin >> t[i + 1] >> l[i + 1] >> r[i + 1]; }

	vector<vector<mint>> dp(n + 1, vector<mint>(n + 1, 0));
	dp[0][0] = 1;

	using tup = tuple<int, int, mint>;
	queue<tup> q;

	rep(i, n) {
		int now = i + 1;
		rep(j, now) {
			rep(k, now) {
				if(r[k] + (t[now] - t[k]) < l[now]) continue;
				if(r[now] < l[j] - (t[now] - t[j])) continue;
				int a, b;
				a = j, b = k;
				if(l[j] - (t[now] - t[j]) < l[now]) {
					a = now;
				}
				if(r[k] + (t[now] - t[k]) > r[now]) {
					b = now;
				}
				// debug(a, b, dp[j][k]);
				//if(l[a] > r[b]) continue;
				q.push((tup){a, b, dp[j][k]});
			}
		}
		while(!q.empty()) {
			int a, b;
			mint r;
			tie(a, b, r) = q.front();
			q.pop();
			dp[a][b] += r;
		}
	}

	mint ans = -1;
	rep(i, n + 1) rep(j, n + 1) { ans += dp[i][j]; }

	drop(ans);

	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 5020
final_rank: 4

code_snippet: // #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region aliases

#define rep(i, n) for(long long i = 0; i < (n); i++)
#define rrep(i, n) for(long long i = (n)-1; i > -1; i--)
#define Rep(i, m, n) for(long long i = (m); i < (n); i++)
#define rRep(i, m, n) for(long long i = (n)-1; i >= (m); i--)
#define REP(i, m, n, p) for(long long i = m; i < n; i += p)
#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define bcnt(n) __builtin_popcountll(n)
#define endk endl
#define ednl endl
#define enld endl

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vb = vector<bool>;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using mll = map<long long, long long>;
using pll = pair<long long, long long>;
using qll = queue<long long>;
using sll = set<long long>;
using vpll = vector<pair<long long, long long>>;
template <class T = ll>
using V = vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
//昇順pq(小さい方から取り出す)
template <class T = ll>
using pqup = priority_queue<T, vector<T>, greater<T>>;
//降順pq(大きい方から取り出す)
template <class T = ll>
using pqdn = priority_queue<T>;

#pragma endregion

#pragma region constants

long long const limLL = 9223372036854775807;  // POW(2,63)-1 ~ 9.22e18
long long const dekai = 3e16;
const long double pi = acos(-1);
const char dl = '\n';
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
int ddx[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int ddy[8] = {-1, 0, 1, -1, 1, -1, 0, 1};

// const int mod = 1000000007;
const int mod = 998244353;

#pragma endregion

#pragma region basic_procedure

template <class T>
inline bool isin(T x, T lef, T rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { cout << (f ? "Yes" : "No") << "\n"; }
void No() { cout << "No\n"; }
void YES(bool f = 1) { cout << (f ? "YES" : "NO") << "\n"; }
void NO() { cout << "NO\n"; }
template <class T>
void drop(T answer) {
	cout << answer << "\n";
	exit(0);
}
void err() {
	cout << -1 << "\n";
	exit(0);
}

template <class T>
void vout(vector<T> &v, bool tate = 0) {
	if(v.size() > 0) {
		for(auto it = v.begin(); it < v.end(); it++) {
			cout << *it;
			if(it != v.end() - 1) {
				if(tate)
					cout << endl;
				else
					cout << " ";
			}
		}
	}
	cout << endl;
}

template <class T>
void add(vector<T> &v, T val) {	 //ベクトルの各要素に加算
	for(auto &a : v) a += val;
	return;
}

// vectorの中身を数える map<要素,個数>を返す
template <class T>
map<T, long long> cntv(vector<T> v) {
	map<T, long long> m;
	for(auto &g : v) {
		if(m.count(g))
			m[g]++;
		else
			m[g] = 1;
	}
	return m;
}

//配列圧縮
//{1,36,1,3,8,-2,-92}を
//{2, 5,2,3,4, 1,  0}にする
template <class T>
vector<long long> press(vector<T> &v) {
	long long n = v.size();
	vector<long long> w(n);
	map<T, long long> m;
	for(T &p : v) m[p] = 0;
	long long i = 0;
	for(auto &p : m) {
		p.second = i;
		i++;
	}
	for(long long i = 0; i < n; i++) w.at(i) = m[v.at(i)];
	return w;
}

// 切り上げ除算
template <class T>
T dup(T a, T b) {
	assert(b != 0);
	T x = abs(a);
	T y = abs(b);
	T z = (x + y - 1) / y;
	if((a < 0 && b > 0) || (a > 0 && b < 0))
		return -z;
	else if(a == 0)
		return 0;
	else
		return z;
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	if(mod == 1) return 0LL;
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res;
}

// a * x % mod == __gcd(a,mod)なるxを返す
// a が modの倍数でないことが条件
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		swap(a, b);
		u -= t * v;
		swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

vvll comb(100, vll(100, -1));
long long com(long long n, long long k) {  //普通の二項計数(overflowに注意)
	assert(n < 100 && k < 100);
	if(n < k || k < 0 || n < 0) return 0;
	if(comb[n][k] != -1) return comb[n][k];
	ll res;
	if(n - k < k)
		res = com(n, n - k);
	else if(k == 0)
		res = 1;
	else
		res = com(n - 1, k - 1) + com(n - 1, k);
	comb[n][k] = res;
	return res;
}

// nCk modを求める
const int MAX = 5100000;
// この値は求める二項計数の値に応じて変える
// MAX=3*10^7のとき1900msほど、ほぼ比例
// MAX=5*10^6程度ならそれほど気にしなくてよい(300ms程)
long long fac[MAX], finv[MAX], inv[MAX];

void cominit() {
	// テーブルを作る前処理
	fac[0] = fac[1] = 1;
	finv[0] = finv[1] = 1;
	inv[1] = 1;
	for(int i = 2; i < MAX; i++) {
		fac[i] = fac[i - 1] * i % mod;
		inv[i] = mod - inv[mod % i] * (mod / i) % mod;
		finv[i] = finv[i - 1] * inv[i] % mod;
	}
}
long long commod(long long n, long long k) {  // 二項係数
	if(n < k) return 0;
	if(n < 0 || k < 0) return 0;
	return fac[n] * (finv[k] * finv[n - k] % mod) % mod;
}
long long pmod(long long n, long long k) {	// 順列
	if(n < k) return 0;
	if(n < 0 || k < 0) return 0;
	return fac[n] * finv[n - k] % mod;
}
// n個の区別しないボールを区別するk個の箱に入れる方法の総数
long long hmod(long long n, long long k) {	// 重複組み合わせ
	return commod(n + k - 1, n);
}
#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define CHAR(...)     \
	char __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define DOUBLE(...)     \
	double __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	INPUT(__VA_ARGS__)

template <class T>
void scan(T &a) {
	cin >> a;
}
template <class T>
void scan(vector<T> &a) {
	for(auto &i : a) scan(i);
}
template <class T, class L>
void scan(pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}
void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
template <class T>
inline void print(T x) {
	cout << x << '\n';
}

template <typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	cerr << ", ";
	view(p.second);
	cerr << ")";
}

template <typename T>
void view(std::set<T> &s) {
	if(s.empty()) {
		cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << "\n";
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		cerr << ", ";
		view(c.second);
		cerr << ")\n";
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		cerr << "] : ";
		view(t.second);
		cerr << "\n";
	}
	std::cerr << "}";
}

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	view(H);
	cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                           \
	do {                                                     \
		cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                              \
		cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                 \
	do {                                        \
		cerr << __LINE__ << " " << #x << " : "; \
		view(x);                                \
		cerr << "\n";                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region modint

template <int mod>
struct ModInt {
	int x;
	ModInt() : x(0) {}
	ModInt(long long y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
	ModInt &operator+=(const ModInt &p) {
		if((x += p.x) >= mod) x -= mod;
		return *this;
	}
	ModInt &operator-=(const ModInt &p) {
		if((x += mod - p.x) >= mod) x -= mod;
		return *this;
	}
	ModInt &operator*=(const ModInt &p) {
		x = (int)(1LL * x * p.x % mod);
		return *this;
	}
	ModInt &operator/=(const ModInt &p) {
		*this *= p.inverse();
		return *this;
	}
	ModInt operator-() const { return ModInt(-x); }
	ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
	ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
	ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
	ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
	bool operator==(const ModInt &p) const { return x == p.x; }
	bool operator!=(const ModInt &p) const { return x != p.x; }
	ModInt inverse() const {
		int a = x, b = mod, u = 1, v = 0, t;
		while(b > 0) {
			t = a / b;
			swap(a -= t * b, b);
			swap(u -= t * v, v);
		}
		return ModInt(u);
	}
	ModInt pow(long long n) const {
		ModInt ret(1), mul(x);
		while(n > 0) {
			if(n & 1) ret *= mul;
			mul *= mul;
			n >>= 1;
		}
		return ret;
	}
	friend ostream &operator<<(ostream &os, const ModInt &p) { return os << p.x; }
	friend istream &operator>>(istream &is, ModInt &a) {
		long long t;
		is >> t;
		a = ModInt<mod>(t);
		return (is);
	}
	static int get_mod() { return mod; }
};
using mint = ModInt<mod>;

#pragma endregion

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout << fixed << setprecision(15);
	srand((unsigned)time(NULL));

	INT(n);
	vector<int> t(n + 1), l(n + 1), r(n + 1);
	rep(i, n) { cin >> t[i + 1] >> l[i + 1] >> r[i + 1]; }

	vector<vector<mint>> dp(n + 1, vector<mint>(n + 1, 0));
	dp[0][0] = 1;

	using tup = tuple<int, int, mint>;
	queue<tup> q;

	rep(i, n) {
		int now = i + 1;
		rep(j, now) {
			rep(k, now) {
				if(r[k] + (t[now] - t[k]) < l[now]) continue;
				if(r[now] < l[j] - (t[now] - t[j])) continue;
				int a, b;
				a = j, b = k;
				if(l[j] - (t[now] - t[j]) < l[now]) {
					a = now;
				}
				if(r[k] + (t[now] - t[k]) > r[now]) {
					b = now;
				}
				// debug(a, b, dp[j][k]);
				// if(l[a] > r[b]) continue;
				q.push((tup){a, b, dp[j][k]});
			}
		}
		while(!q.empty()) {
			int a, b;
			mint r;
			tie(a, b, r) = q.front();
			q.pop();
			dp[a][b] += r;
		}
		// dump(dp);
	}

	mint ans = -1;
	rep(i, n + 1) rep(j, n + 1) { ans += dp[i][j]; }

	drop(ans);

	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 5016
final_rank: 3

code_snippet: // #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region aliases

#define rep(i, n) for(long long i = 0; i < (n); i++)
#define rrep(i, n) for(long long i = (n)-1; i > -1; i--)
#define Rep(i, m, n) for(long long i = (m); i < (n); i++)
#define rRep(i, m, n) for(long long i = (n)-1; i >= (m); i--)
#define REP(i, m, n, p) for(long long i = m; i < n; i += p)
#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define bcnt(n) __builtin_popcountll(n)
#define endk endl
#define ednl endl
#define enld endl

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vb = vector<bool>;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using mll = map<long long, long long>;
using pll = pair<long long, long long>;
using qll = queue<long long>;
using sll = set<long long>;
using vpll = vector<pair<long long, long long>>;
template <class T = ll>
using V = vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
//昇順pq(小さい方から取り出す)
template <class T = ll>
using pqup = priority_queue<T, vector<T>, greater<T>>;
//降順pq(大きい方から取り出す)
template <class T = ll>
using pqdn = priority_queue<T>;

#pragma endregion

#pragma region constants

long long const limLL = 9223372036854775807;  // POW(2,63)-1 ~ 9.22e18
long long const dekai = 3e16;
const long double pi = acos(-1);
const char dl = '\n';
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
int ddx[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int ddy[8] = {-1, 0, 1, -1, 1, -1, 0, 1};

// const int mod = 1000000007;
const int mod = 998244353;

#pragma endregion

#pragma region basic_procedure

template <class T>
inline bool isin(T x, T lef, T rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { cout << (f ? "Yes" : "No") << "\n"; }
void No() { cout << "No\n"; }
void YES(bool f = 1) { cout << (f ? "YES" : "NO") << "\n"; }
void NO() { cout << "NO\n"; }
template <class T>
void drop(T answer) {
	cout << answer << "\n";
	exit(0);
}
void err() {
	cout << -1 << "\n";
	exit(0);
}

template <class T>
void vout(vector<T> &v, bool tate = 0) {
	if(v.size() > 0) {
		for(auto it = v.begin(); it < v.end(); it++) {
			cout << *it;
			if(it != v.end() - 1) {
				if(tate)
					cout << endl;
				else
					cout << " ";
			}
		}
	}
	cout << endl;
}

template <class T>
void add(vector<T> &v, T val) {	 //ベクトルの各要素に加算
	for(auto &a : v) a += val;
	return;
}

// vectorの中身を数える map<要素,個数>を返す
template <class T>
map<T, long long> cntv(vector<T> v) {
	map<T, long long> m;
	for(auto &g : v) {
		if(m.count(g))
			m[g]++;
		else
			m[g] = 1;
	}
	return m;
}

//配列圧縮
//{1,36,1,3,8,-2,-92}を
//{2, 5,2,3,4, 1,  0}にする
template <class T>
vector<long long> press(vector<T> &v) {
	long long n = v.size();
	vector<long long> w(n);
	map<T, long long> m;
	for(T &p : v) m[p] = 0;
	long long i = 0;
	for(auto &p : m) {
		p.second = i;
		i++;
	}
	for(long long i = 0; i < n; i++) w.at(i) = m[v.at(i)];
	return w;
}

// 切り上げ除算
template <class T>
T dup(T a, T b) {
	assert(b != 0);
	T x = abs(a);
	T y = abs(b);
	T z = (x + y - 1) / y;
	if((a < 0 && b > 0) || (a > 0 && b < 0))
		return -z;
	else if(a == 0)
		return 0;
	else
		return z;
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	if(mod == 1) return 0LL;
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res;
}

// a * x % mod == __gcd(a,mod)なるxを返す
// a が modの倍数でないことが条件
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		swap(a, b);
		u -= t * v;
		swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

vvll comb(100, vll(100, -1));
long long com(long long n, long long k) {  //普通の二項計数(overflowに注意)
	assert(n < 100 && k < 100);
	if(n < k || k < 0 || n < 0) return 0;
	if(comb[n][k] != -1) return comb[n][k];
	ll res;
	if(n - k < k)
		res = com(n, n - k);
	else if(k == 0)
		res = 1;
	else
		res = com(n - 1, k - 1) + com(n - 1, k);
	comb[n][k] = res;
	return res;
}

// nCk modを求める
const int MAX = 5100000;
// この値は求める二項計数の値に応じて変える
// MAX=3*10^7のとき1900msほど、ほぼ比例
// MAX=5*10^6程度ならそれほど気にしなくてよい(300ms程)
long long fac[MAX], finv[MAX], inv[MAX];

void cominit() {
	// テーブルを作る前処理
	fac[0] = fac[1] = 1;
	finv[0] = finv[1] = 1;
	inv[1] = 1;
	for(int i = 2; i < MAX; i++) {
		fac[i] = fac[i - 1] * i % mod;
		inv[i] = mod - inv[mod % i] * (mod / i) % mod;
		finv[i] = finv[i - 1] * inv[i] % mod;
	}
}
long long commod(long long n, long long k) {  // 二項係数
	if(n < k) return 0;
	if(n < 0 || k < 0) return 0;
	return fac[n] * (finv[k] * finv[n - k] % mod) % mod;
}
long long pmod(long long n, long long k) {	// 順列
	if(n < k) return 0;
	if(n < 0 || k < 0) return 0;
	return fac[n] * finv[n - k] % mod;
}
// n個の区別しないボールを区別するk個の箱に入れる方法の総数
long long hmod(long long n, long long k) {	// 重複組み合わせ
	return commod(n + k - 1, n);
}
#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define CHAR(...)     \
	char __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define DOUBLE(...)     \
	double __VA_ARGS__; \
	INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	INPUT(__VA_ARGS__)

template <class T>
void scan(T &a) {
	cin >> a;
}
template <class T>
void scan(vector<T> &a) {
	for(auto &i : a) scan(i);
}
template <class T, class L>
void scan(pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}
void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
template <class T>
inline void print(T x) {
	cout << x << '\n';
}

template <typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	cerr << ", ";
	view(p.second);
	cerr << ")";
}

template <typename T>
void view(std::set<T> &s) {
	if(s.empty()) {
		cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << "\n";
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		cerr << ", ";
		view(c.second);
		cerr << ")\n";
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		cerr << "] : ";
		view(t.second);
		cerr << "\n";
	}
	std::cerr << "}";
}

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	view(H);
	cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                           \
	do {                                                     \
		cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                              \
		cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                 \
	do {                                        \
		cerr << __LINE__ << " " << #x << " : "; \
		view(x);                                \
		cerr << "\n";                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region modint

template <int mod>
struct ModInt {
	int x;
	ModInt() : x(0) {}
	ModInt(long long y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
	ModInt &operator+=(const ModInt &p) {
		if((x += p.x) >= mod) x -= mod;
		return *this;
	}
	ModInt &operator-=(const ModInt &p) {
		if((x += mod - p.x) >= mod) x -= mod;
		return *this;
	}
	ModInt &operator*=(const ModInt &p) {
		x = (int)(1LL * x * p.x % mod);
		return *this;
	}
	ModInt &operator/=(const ModInt &p) {
		*this *= p.inverse();
		return *this;
	}
	ModInt operator-() const { return ModInt(-x); }
	ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
	ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
	ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
	ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
	bool operator==(const ModInt &p) const { return x == p.x; }
	bool operator!=(const ModInt &p) const { return x != p.x; }
	ModInt inverse() const {
		int a = x, b = mod, u = 1, v = 0, t;
		while(b > 0) {
			t = a / b;
			swap(a -= t * b, b);
			swap(u -= t * v, v);
		}
		return ModInt(u);
	}
	ModInt pow(long long n) const {
		ModInt ret(1), mul(x);
		while(n > 0) {
			if(n & 1) ret *= mul;
			mul *= mul;
			n >>= 1;
		}
		return ret;
	}
	friend ostream &operator<<(ostream &os, const ModInt &p) { return os << p.x; }
	friend istream &operator>>(istream &is, ModInt &a) {
		long long t;
		is >> t;
		a = ModInt<mod>(t);
		return (is);
	}
	static int get_mod() { return mod; }
};
using mint = ModInt<mod>;

#pragma endregion

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout << fixed << setprecision(15);
	srand((unsigned)time(NULL));

	INT(n);
	vector<int> t(n + 1), l(n + 1), r(n + 1);
	rep(i, n) { cin >> t[i + 1] >> l[i + 1] >> r[i + 1]; }

	vector<vector<mint>> dp(n + 1, vector<mint>(n + 1, 0));
	dp[0][0] = 1;

	using tup = tuple<int, int, mint>;
	queue<tup> q;

	rep(i, n) {
		int now = i + 1;
		rep(j, n + 1) {
			if(j >= now) break;
			rep(k, n + 1) {
				if(k >= now) break;
				if(r[k] + (t[now] - t[k]) < l[now]) continue;
				if(r[now] < l[j] - (t[now] - t[j])) continue;
				int a, b;
				a = j, b = k;
				if(l[j] - (t[now] - t[j]) < l[now]) {
					a = now;
				}
				if(r[j] + (t[now] - t[j]) > r[now]) {
					b = now;
				}
				debug(a, b, dp[j][k]);
				// if(l[a] > r[b]) continue;
				q.push((tup){a, b, dp[j][k]});
			}
		}
		while(!q.empty()) {
			int a, b;
			mint r;
			tie(a, b, r) = q.front();
			q.pop();
			dp[a][b] += r;
		}
		dump(dp);
	}

	mint ans = -1;
	rep(i, n + 1) rep(j, n + 1) { ans += dp[i][j]; }

	drop(ans);

	return 0;
}
accuracy: 0.02564102564102564
time_ms: 40
memory_kb: 4940
final_rank: 19

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

template <int mod = (int)(998244353)>
struct ModInt {
  int x;
  constexpr ModInt() : x(0) {}
  constexpr ModInt(int64_t y)
      : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  constexpr ModInt &operator+=(const ModInt &p) noexcept {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &p) noexcept {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &p) noexcept {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  constexpr ModInt &operator/=(const ModInt &p) noexcept {
    *this *= p.inverse();
    return *this;
  }
  constexpr ModInt operator-() const { return ModInt(-x); }
  constexpr ModInt operator+(const ModInt &p) const noexcept {
    return ModInt(*this) += p;
  }
  constexpr ModInt operator-(const ModInt &p) const noexcept {
    return ModInt(*this) -= p;
  }
  constexpr ModInt operator*(const ModInt &p) const noexcept {
    return ModInt(*this) *= p;
  }
  constexpr ModInt operator/(const ModInt &p) const noexcept {
    return ModInt(*this) /= p;
  }
  constexpr bool operator==(const ModInt &p) const noexcept { return x == p.x; }
  constexpr bool operator!=(const ModInt &p) const noexcept { return x != p.x; }
  constexpr ModInt inverse() const noexcept {
    int a = x, b = mod, u = 1, v = 0, t = 0;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  constexpr ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while (n) {
      if (n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend constexpr ostream &operator<<(ostream &os, const ModInt &p) noexcept {
    return os << p.x;
  }
  friend constexpr istream &operator>>(istream &is, ModInt &a) noexcept {
    int64_t t = 0;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  constexpr int get_mod() { return mod; }
};

struct dat {
  long long t, l, r;
  dat(long long x = 0, long long y = 0, long long z = 0) : t(x), l(y), r(z) {}
  bool operator==(const dat &d) const {
    return t == d.t && l == d.l && r == d.r;
  }
  bool operator<(const dat &d) const {
    if (t != d.t) return t < d.t;
    if (l != d.l) return l < d.l;
    return r < d.r;
  }
  dat operator*(const dat &d) const {
    dat res(d.t, max(d.l, l - (d.t - t)), min(d.r, r + (d.t - t)));
    if (res.l > res.r) res = dat(-1, 0, 0);
    return res;
  }
};

int n;
vector<dat> v;
map<dat, ModInt<>> dp;

ModInt<> solve();

int main() {
  cin >> n;
  v.resize(n);
  for (auto &p : v) cin >> p.t >> p.l >> p.r;
  cout << solve() << endl;
  return 0;
}

ModInt<> solve() {
  dp[dat()] = 1;
  for (int i = 0; i < n; ++i) {
    vector<dat> memod;
    vector<ModInt<>> memoc;
    for (auto [d, c] : dp) {
      dat now = d * v[i];
      if (now.t >= 0) {
        memod.push_back(now);
        memoc.push_back(c);
      }
    }
    int len = memod.size();
    for (int j = 0; j < len; ++j) dp[memod[j]] += memoc[j];
  }
  ModInt<> res = -1;
  for (auto [d, c] : dp) res += c;

  return res;
}
accuracy: 1
time_ms: 370
memory_kb: 19508
final_rank: 8

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

template <int mod = (int)(998244353)>
struct ModInt {
  int x;
  constexpr ModInt() : x(0) {}
  constexpr ModInt(int64_t y)
      : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  constexpr ModInt &operator+=(const ModInt &p) noexcept {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &p) noexcept {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &p) noexcept {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  constexpr ModInt &operator/=(const ModInt &p) noexcept {
    *this *= p.inverse();
    return *this;
  }
  constexpr ModInt operator-() const { return ModInt(-x); }
  constexpr ModInt operator+(const ModInt &p) const noexcept {
    return ModInt(*this) += p;
  }
  constexpr ModInt operator-(const ModInt &p) const noexcept {
    return ModInt(*this) -= p;
  }
  constexpr ModInt operator*(const ModInt &p) const noexcept {
    return ModInt(*this) *= p;
  }
  constexpr ModInt operator/(const ModInt &p) const noexcept {
    return ModInt(*this) /= p;
  }
  constexpr bool operator==(const ModInt &p) const noexcept { return x == p.x; }
  constexpr bool operator!=(const ModInt &p) const noexcept { return x != p.x; }
  constexpr ModInt inverse() const noexcept {
    int a = x, b = mod, u = 1, v = 0, t = 0;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  constexpr ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while (n) {
      if (n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend constexpr ostream &operator<<(ostream &os, const ModInt &p) noexcept {
    return os << p.x;
  }
  friend constexpr istream &operator>>(istream &is, ModInt &a) noexcept {
    int64_t t = 0;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  constexpr int get_mod() { return mod; }
};

struct dat {
  long long t, l, r;
  dat(long long x = 0, long long y = 0, long long z = 0) : t(x), l(y), r(z) {}
  bool operator==(const dat &d) const {
    return t == d.t && l == d.l && r == d.r;
  }
  bool operator<(const dat &d) const {
    if (t != d.t) return t < d.t;
    if (l != d.l) return l < d.l;
    return r < d.r;
  }
  dat operator*(const dat &d) const {
    assert(0 <= t && t < d.t && l <= r && d.l <= d.r);
    dat res(d.t, max(d.l, l - (d.t - t)), min(d.r, r + (d.t - t)));
    if (res.l > res.r) res = dat(-1, 0, 0);
    return res;
  }
};

int n;
vector<dat> v;
map<dat, ModInt<>> dp;

ModInt<> solve();

int main() {
  cin >> n;
  v.resize(n);
  for (auto &p : v) cin >> p.t >> p.l >> p.r;
  cout << solve() << endl;
  return 0;
}

ModInt<> solve() {
  dp[dat()] = 1;
  for (int i = 0; i < n; ++i) {
    vector<dat> memod;
    vector<ModInt<>> memoc;
    for (auto [d, c] : dp) {
      dat now = d * v[i];
      if (now.t >= 0) {
        memod.push_back(now);
        memoc.push_back(c);
      }
    }
    int len = memod.size();
    for (int j = 0; j < len; ++j) {
      if (!dp.count(memod[j]))
        dp[memod[j]] = memoc[j];
      else
        dp[memod[j]] += memoc[j];
    }
  }
  ModInt<> res = -1;
  for (auto [d, c] : dp) {
    assert(d.t >= 0);
    res += c;
  }
  return res;
}
accuracy: 1
time_ms: 610
memory_kb: 19508
final_rank: 9

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

template <int mod = (int)(998244353)>
struct ModInt {
  int x;
  constexpr ModInt() : x(0) {}
  constexpr ModInt(int64_t y)
      : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  constexpr ModInt &operator+=(const ModInt &p) noexcept {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &p) noexcept {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &p) noexcept {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  constexpr ModInt &operator/=(const ModInt &p) noexcept {
    *this *= p.inverse();
    return *this;
  }
  constexpr ModInt operator-() const { return ModInt(-x); }
  constexpr ModInt operator+(const ModInt &p) const noexcept {
    return ModInt(*this) += p;
  }
  constexpr ModInt operator-(const ModInt &p) const noexcept {
    return ModInt(*this) -= p;
  }
  constexpr ModInt operator*(const ModInt &p) const noexcept {
    return ModInt(*this) *= p;
  }
  constexpr ModInt operator/(const ModInt &p) const noexcept {
    return ModInt(*this) /= p;
  }
  constexpr bool operator==(const ModInt &p) const noexcept { return x == p.x; }
  constexpr bool operator!=(const ModInt &p) const noexcept { return x != p.x; }
  constexpr ModInt inverse() const noexcept {
    int a = x, b = mod, u = 1, v = 0, t = 0;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  constexpr ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while (n) {
      if (n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend constexpr ostream &operator<<(ostream &os, const ModInt &p) noexcept {
    return os << p.x;
  }
  friend constexpr istream &operator>>(istream &is, ModInt &a) noexcept {
    int64_t t = 0;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  constexpr int get_mod() { return mod; }
};

struct dat {
  long long t, l, r;
  dat(long long x = 0, long long y = 0, long long z = 0) : t(x), l(y), r(z) {}
  bool operator==(const dat &d) const {
    return t == d.t && l == d.l && r == d.r;
  }
  bool operator<(const dat &d) const {
    if (t != d.t) return t < d.t;
    if (l != d.r) return l < d.l;
    return r < d.r;
  }
  dat operator*(const dat &d) const {
    assert(0 <= t && t < d.t && l <= r && d.l <= d.r);
    dat res(d.t, max(d.l, l - (d.t - t)), min(d.r, r + (d.t - t)));
    if (res.l > res.r) res = dat(-1, 0, 0);
    return res;
  }
};

int n;
vector<dat> v;
map<dat, ModInt<>> dp;

ModInt<> solve();

int main() {
  cin >> n;
  v.resize(n);
  for (auto &p : v) cin >> p.t >> p.l >> p.r;
  cout << solve() << endl;
  return 0;
}

ModInt<> solve() {
  dp[dat()] = 1;
  for (int i = 0; i < n; ++i) {
    vector<dat> memod;
    vector<ModInt<>> memoc;
    for (auto [d, c] : dp) {
      dat now = d * v[i];
      if (now.t >= 0) {
        memod.push_back(now);
        memoc.push_back(c);
      }
    }
    int len = memod.size();
    for (int j = 0; j < len; ++j) {
      if (!dp.count(memod[j]))
        dp[memod[j]] = memoc[j];
      else
        dp[memod[j]] += memoc[j];
    }
  }
  ModInt<> res = -1;
  for (auto [d, c] : dp) {
    assert(d.t >= 0);
    res += c;
  }
  return res;
}
accuracy: 0.02564102564102564
time_ms: 20
memory_kb: 3880
final_rank: 17

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

template <int mod = (int)(998244353)>
struct ModInt {
  int x;
  constexpr ModInt() : x(0) {}
  constexpr ModInt(int64_t y)
      : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  constexpr ModInt &operator+=(const ModInt &p) noexcept {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &p) noexcept {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &p) noexcept {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  constexpr ModInt &operator/=(const ModInt &p) noexcept {
    *this *= p.inverse();
    return *this;
  }
  constexpr ModInt operator-() const { return ModInt(-x); }
  constexpr ModInt operator+(const ModInt &p) const noexcept {
    return ModInt(*this) += p;
  }
  constexpr ModInt operator-(const ModInt &p) const noexcept {
    return ModInt(*this) -= p;
  }
  constexpr ModInt operator*(const ModInt &p) const noexcept {
    return ModInt(*this) *= p;
  }
  constexpr ModInt operator/(const ModInt &p) const noexcept {
    return ModInt(*this) /= p;
  }
  constexpr bool operator==(const ModInt &p) const noexcept { return x == p.x; }
  constexpr bool operator!=(const ModInt &p) const noexcept { return x != p.x; }
  constexpr ModInt inverse() const noexcept {
    int a = x, b = mod, u = 1, v = 0, t = 0;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  constexpr ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while (n) {
      if (n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend constexpr ostream &operator<<(ostream &os, const ModInt &p) noexcept {
    return os << p.x;
  }
  friend constexpr istream &operator>>(istream &is, ModInt &a) noexcept {
    int64_t t = 0;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  constexpr int get_mod() { return mod; }
};

struct dat {
  long long t, l, r;
  dat(long long x = 0, long long y = 0, long long z = 0) : t(x), l(y), r(z) {}
  bool operator==(const dat &d) const {
    return t == d.t && l == d.l && r == d.r;
  }
  bool operator<(const dat &d) const {
    if (t != d.t) return t < d.t;
    if (l != d.r) return l < d.l;
    return r < d.r;
  }
  dat operator*(const dat &d) const {
    assert(0 <= t && t < d.t && l <= r && d.l <= d.r);
    dat res(d.t, max(d.l, l - (d.t - t)), min(d.r, r + (d.t - t)));
    if (res.l > res.r) res = dat(-1, 0, 0);
    return res;
  }
};

int n;
vector<dat> v;
map<dat, ModInt<>> dp;

ModInt<> solve();

int main() {
  cin >> n;
  v.resize(n);
  for (int i = 0; i < n; ++i) cin >> v[i].t >> v[i].l >> v[i].r;
  cout << solve() << endl;
  return 0;
}

ModInt<> solve() {
  dp[dat()] = 1;
  for (int i = 0; i < n; ++i) {
    vector<dat> memod;
    vector<ModInt<>> memoc;
    for (auto [d, c] : dp) {
      dat now = d * v[i];
      if (now.t >= 0) {
        memod.push_back(now);
        memoc.push_back(c);
      }
    }
    int len = memod.size();
    for (int j = 0; j < len; ++j) dp[memod[j]] += memoc[j];
  }
  ModInt<> res = -1;
  for (auto [d, c] : dp) {
    assert(d.t >= 0);
    res += c;
  }
  return res;
}
accuracy: 0.02564102564102564
time_ms: 10
memory_kb: 3960
final_rank: 13

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

template <int mod = (int)(998244353)>
struct ModInt {
  int x;
  constexpr ModInt() : x(0) {}
  constexpr ModInt(int64_t y)
      : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  constexpr ModInt &operator+=(const ModInt &p) noexcept {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &p) noexcept {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &p) noexcept {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  constexpr ModInt &operator/=(const ModInt &p) noexcept {
    *this *= p.inverse();
    return *this;
  }
  constexpr ModInt operator-() const { return ModInt(-x); }
  constexpr ModInt operator+(const ModInt &p) const noexcept {
    return ModInt(*this) += p;
  }
  constexpr ModInt operator-(const ModInt &p) const noexcept {
    return ModInt(*this) -= p;
  }
  constexpr ModInt operator*(const ModInt &p) const noexcept {
    return ModInt(*this) *= p;
  }
  constexpr ModInt operator/(const ModInt &p) const noexcept {
    return ModInt(*this) /= p;
  }
  constexpr bool operator==(const ModInt &p) const noexcept { return x == p.x; }
  constexpr bool operator!=(const ModInt &p) const noexcept { return x != p.x; }
  constexpr ModInt inverse() const noexcept {
    int a = x, b = mod, u = 1, v = 0, t = 0;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  constexpr ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while (n) {
      if (n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend constexpr ostream &operator<<(ostream &os, const ModInt &p) noexcept {
    return os << p.x;
  }
  friend constexpr istream &operator>>(istream &is, ModInt &a) noexcept {
    int64_t t = 0;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  constexpr int get_mod() { return mod; }
};

struct dat {
  long long t, l, r;
  dat(long long x = 0, long long y = 0, long long z = 0) : t(x), l(y), r(z) {}
  bool operator==(const dat &d) const {
    return t == d.t && l == d.l && r == d.r;
  }
  bool operator<(const dat &d) const {
    if (t != d.t) return t < d.t;
    if (l != d.r) return l < d.l;
    return r < d.r;
  }
  dat operator*(const dat &d) const {
    if (t < 0) return dat(-1, 0, 0);
    assert(t < d.t && l <= r && d.l <= d.r);
    dat res(d.t, max(d.l, l - (d.t - t)), min(d.r, r + (d.t - t)));
    if (res.l > res.r) res = dat(-1, 0, 0);
    return res;
  }
};

int n;
vector<dat> v;
map<dat, ModInt<>> dp;

ModInt<> solve();

int main() {
  cin >> n;
  v.resize(n);
  for (int i = 0; i < n; ++i) cin >> v[i].t >> v[i].l >> v[i].r;
  cout << solve() << endl;
  return 0;
}

ModInt<> solve() {
  dp[dat()] = 1;
  for (int i = 0; i < n; ++i) {
    vector<dat> memod;
    vector<ModInt<>> memoc;
    for (auto [d, c] : dp) {
      dat now = d * v[i];
      if (now.t >= 0) {
        memod.push_back(now);
        memoc.push_back(c);
      }
    }
    int len = memod.size();
    for (int j = 0; j < len; ++j) dp[memod[j]] += memoc[j];
  }
  ModInt<> res = -1;
  for (auto [d, c] : dp) {
    assert(d.t >= 0);
    res += c;
  }
  return res;
}
accuracy: 0.02564102564102564
time_ms: 10
memory_kb: 4004
final_rank: 15

code_snippet: #include <iostream>
#include <map>

template <int MOD>
struct ModInt {
    using lint = long long;
    int val;

    // constructor
    ModInt(lint v = 0) : val(v % MOD) {
        if (val < 0) val += MOD;
    };

    // unary operator
    ModInt operator+() const { return ModInt(val); }
    ModInt operator-() const { return ModInt(MOD - val); }
    ModInt inv() const { return this->pow(MOD - 2); }

    // arithmetic
    ModInt operator+(const ModInt& x) const { return ModInt(*this) += x; }
    ModInt operator-(const ModInt& x) const { return ModInt(*this) -= x; }
    ModInt operator*(const ModInt& x) const { return ModInt(*this) *= x; }
    ModInt operator/(const ModInt& x) const { return ModInt(*this) /= x; }
    ModInt pow(lint n) const {
        auto x = ModInt(1);
        auto b = *this;
        while (n > 0) {
            if (n & 1) x *= b;
            n >>= 1;
            b *= b;
        }
        return x;
    }

    // compound assignment
    ModInt& operator+=(const ModInt& x) {
        if ((val += x.val) >= MOD) val -= MOD;
        return *this;
    }
    ModInt& operator-=(const ModInt& x) {
        if ((val -= x.val) < 0) val += MOD;
        return *this;
    }
    ModInt& operator*=(const ModInt& x) {
        val = lint(val) * x.val % MOD;
        return *this;
    }
    ModInt& operator/=(const ModInt& x) { return *this *= x.inv(); }

    // compare
    bool operator==(const ModInt& b) const { return val == b.val; }
    bool operator!=(const ModInt& b) const { return val != b.val; }
    bool operator<(const ModInt& b) const { return val < b.val; }
    bool operator<=(const ModInt& b) const { return val <= b.val; }
    bool operator>(const ModInt& b) const { return val > b.val; }
    bool operator>=(const ModInt& b) const { return val >= b.val; }

    // I/O
    friend std::istream& operator>>(std::istream& is, ModInt& x) noexcept {
        lint v;
        is >> v;
        x = v;
        return is;
    }
    friend std::ostream& operator<<(std::ostream& os, const ModInt& x) noexcept { return os << x.val; }
};

constexpr int MOD = 998244353;
using mint = ModInt<MOD>;

void solve() {
    int n;
    std::cin >> n;

    // [L, R]に自由に移動できるときの通り数
    std::map<std::pair<int, int>, mint> dp;
    dp[std::make_pair(0, 0)] = 1;

    int pt = 0;  // 前の命令の時刻
    while (n--) {
        int t, l, r;
        std::cin >> t >> l >> r;

        std::map<std::pair<int, int>, mint> ndp;
        for (auto [p, v] : dp) {
            auto [pl, pr] = p;

            // 左右に引き伸ばす
            pl -= t - pt;
            pr += t - pt;

            {
                // 守らない場合
                auto q = std::make_pair(pl, pr);
                if (!ndp.count(q)) ndp[q] = 0;
                ndp[q] += v;
            }

            // 守る場合
            pl = std::max(pl, l);
            pr = std::min(pr, r);
            if (pr < pl) continue;

            {
                auto q = std::make_pair(pl, pr);
                if (!ndp.count(q)) ndp[q] = 0;
                ndp[q] += v;
            }
        }

        std::swap(dp, ndp);
        pt = t;
    }

    mint ans = 0;
    for (auto [p, v] : dp) ans += v;
    std::cout << ans - 1 << "\n";
}

int main() {
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 4416
final_rank: 5

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

template <int mod = (int)(998244353)>
struct ModInt {
  int x;
  constexpr ModInt() : x(0) {}
  constexpr ModInt(int64_t y)
      : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  constexpr ModInt &operator+=(const ModInt &p) noexcept {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &p) noexcept {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &p) noexcept {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  constexpr ModInt &operator/=(const ModInt &p) noexcept {
    *this *= p.inverse();
    return *this;
  }
  constexpr ModInt operator-() const { return ModInt(-x); }
  constexpr ModInt operator+(const ModInt &p) const noexcept {
    return ModInt(*this) += p;
  }
  constexpr ModInt operator-(const ModInt &p) const noexcept {
    return ModInt(*this) -= p;
  }
  constexpr ModInt operator*(const ModInt &p) const noexcept {
    return ModInt(*this) *= p;
  }
  constexpr ModInt operator/(const ModInt &p) const noexcept {
    return ModInt(*this) /= p;
  }
  constexpr bool operator==(const ModInt &p) const noexcept { return x == p.x; }
  constexpr bool operator!=(const ModInt &p) const noexcept { return x != p.x; }
  constexpr ModInt inverse() const noexcept {
    int a = x, b = mod, u = 1, v = 0, t = 0;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  constexpr ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while (n) {
      if (n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend constexpr ostream &operator<<(ostream &os, const ModInt &p) noexcept {
    return os << p.x;
  }
  friend constexpr istream &operator>>(istream &is, ModInt &a) noexcept {
    int64_t t = 0;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  constexpr int get_mod() { return mod; }
};

struct dat {
  long long t, l, r;
  dat(long long x = 0, long long y = 0, long long z = 0) : t(x), l(y), r(z) {}
  bool operator==(const dat &d) const {
    return t == d.t && l == d.l && r == d.r;
  }
  bool operator<(const dat &d) const {
    if (t != d.t) return t < d.t;
    if (l != d.r) return l < d.l;
    return r < d.r;
  }
  dat operator*(const dat &d) const {
    if (t < 0) return dat(-1, 0, 0);
    assert(t < d.t);
    dat res(d.t, max(d.l, l - (d.t - t)), min(d.r, r + (d.t - t)));
    if (res.l > res.r) res = dat(-1, 0, 0);
    return res;
  }
};

int n;
vector<dat> v;
map<dat, ModInt<>> dp;

ModInt<> solve();

int main() {
  cin >> n;
  v.resize(n);
  for (int i = 0; i < n; ++i) cin >> v[i].t >> v[i].l >> v[i].r;
  cout << solve() << endl;
  return 0;
}

ModInt<> solve() {
  dp[dat()] = 1;
  for (int i = 0; i < n; ++i) {
    vector<dat> memod;
    vector<ModInt<>> memoc;
    for (auto [d, c] : dp) {
      dat now = d * v[i];
      if (now.t >= 0) {
        memod.push_back(now);
        memoc.push_back(c);
      }
    }
    int len = memod.size();
    for (int j = 0; j < len; ++j) dp[memod[j]] += memoc[j];
  }
  ModInt<> res = -1;
  for (auto [d, c] : dp) res += c;
  return res;
}
accuracy: 0.02564102564102564
time_ms: 10
memory_kb: 3880
final_rank: 12

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

template <int mod = (int)(998244353)>
struct ModInt {
  int x;
  constexpr ModInt() : x(0) {}
  constexpr ModInt(int64_t y)
      : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  constexpr ModInt &operator+=(const ModInt &p) noexcept {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &p) noexcept {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &p) noexcept {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  constexpr ModInt &operator/=(const ModInt &p) noexcept {
    *this *= p.inverse();
    return *this;
  }
  constexpr ModInt operator-() const { return ModInt(-x); }
  constexpr ModInt operator+(const ModInt &p) const noexcept {
    return ModInt(*this) += p;
  }
  constexpr ModInt operator-(const ModInt &p) const noexcept {
    return ModInt(*this) -= p;
  }
  constexpr ModInt operator*(const ModInt &p) const noexcept {
    return ModInt(*this) *= p;
  }
  constexpr ModInt operator/(const ModInt &p) const noexcept {
    return ModInt(*this) /= p;
  }
  constexpr bool operator==(const ModInt &p) const noexcept { return x == p.x; }
  constexpr bool operator!=(const ModInt &p) const noexcept { return x != p.x; }
  constexpr ModInt inverse() const noexcept {
    int a = x, b = mod, u = 1, v = 0, t = 0;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  constexpr ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while (n) {
      if (n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend constexpr ostream &operator<<(ostream &os, const ModInt &p) noexcept {
    return os << p.x;
  }
  friend constexpr istream &operator>>(istream &is, ModInt &a) noexcept {
    int64_t t = 0;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  constexpr int get_mod() { return mod; }
};

struct dat {
  int t, l, r;
  dat(int x = 0, int y = 0, int z = 0) : t(x), l(y), r(z) {}
  bool operator==(const dat &d) const {
    return t == d.t && l == d.l && r == d.r;
  }
  bool operator<(const dat &d) const {
    if (t != d.t) return t < d.t;
    if (l != d.r) return l < d.l;
    return r < d.r;
  }
  dat operator*(const dat &d) const {
    if (t < 0) return dat(-1, 0, 0);
    dat res(d.t, max(d.l, l - (d.t - t)), min(d.r, r + (d.t - t)));
    if (res.l > res.r || res.r < d.l || d.r < res.l) res = dat(-1, 0, 0);
    return res;
  }
};

int n;
vector<dat> v;
map<dat, ModInt<>> dp;

ModInt<> solve();

int main() {
  cin >> n;
  v.resize(n);
  for (int i = 0; i < n; ++i) cin >> v[i].t >> v[i].l >> v[i].r;
  cout << solve() << endl;
  return 0;
}

ModInt<> solve() {
  dp[dat()] = 1;
  for (int i = 0; i < n; ++i) {
    vector<dat> memod;
    vector<ModInt<>> memoc;
    for (auto [d, c] : dp) {
      dat now = d * v[i];
      if (now.t >= 0) {
        memod.push_back(now);
        memoc.push_back(c);
      }
    }
    int len = memod.size();
    for (int j = 0; j < len; ++j) dp[memod[j]] += memoc[j];
  }
  ModInt<> res = -1;
  for (auto [d, c] : dp) res += c;
  return res;
}
accuracy: 0.02564102564102564
time_ms: 10
memory_kb: 3964
final_rank: 14

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

template <int mod = (int)(998244353)>
struct ModInt {
  int x;
  constexpr ModInt() : x(0) {}
  constexpr ModInt(int64_t y)
      : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  constexpr ModInt &operator+=(const ModInt &p) noexcept {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &p) noexcept {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &p) noexcept {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  constexpr ModInt &operator/=(const ModInt &p) noexcept {
    *this *= p.inverse();
    return *this;
  }
  constexpr ModInt operator-() const { return ModInt(-x); }
  constexpr ModInt operator+(const ModInt &p) const noexcept {
    return ModInt(*this) += p;
  }
  constexpr ModInt operator-(const ModInt &p) const noexcept {
    return ModInt(*this) -= p;
  }
  constexpr ModInt operator*(const ModInt &p) const noexcept {
    return ModInt(*this) *= p;
  }
  constexpr ModInt operator/(const ModInt &p) const noexcept {
    return ModInt(*this) /= p;
  }
  constexpr bool operator==(const ModInt &p) const noexcept { return x == p.x; }
  constexpr bool operator!=(const ModInt &p) const noexcept { return x != p.x; }
  constexpr ModInt inverse() const noexcept {
    int a = x, b = mod, u = 1, v = 0, t = 0;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  constexpr ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while (n) {
      if (n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend constexpr ostream &operator<<(ostream &os, const ModInt &p) noexcept {
    return os << p.x;
  }
  friend constexpr istream &operator>>(istream &is, ModInt &a) noexcept {
    int64_t t = 0;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  constexpr int get_mod() { return mod; }
};

struct dat {
  int t, l, r;
  dat(int x = 0, int y = 0, int z = 0) : t(x), l(y), r(z) {}
  bool operator==(const dat &d) const {
    return t == d.t && l == d.l && r == d.r;
  }
  dat operator*(const dat &d) const {
    if (t < 0) return dat(-1, 0, 0);
    dat res(d.t, max(d.l, l - (d.t - t)), min(d.r, r + (d.t - t)));
    if (res.l > res.r || res.r < d.l || d.r < res.l) res = dat(-1, 0, 0);
    return res;
  }
};

int n;
vector<dat> v;
vector<vector<dat>> memo;
vector<vector<ModInt<>>> dp;

ModInt<> solve();

int main() {
  cin >> n;
  v.resize(n + 1);
  for (int i = 1; i <= n; ++i) cin >> v[i].t >> v[i].l >> v[i].r;
  cout << solve() << endl;
  return 0;
}

ModInt<> solve() {
  {  // pre calc
    memo.resize(n + 1, vector<dat>(n + 1));
    for (int i = 0; i <= n; ++i)
      for (int j = i; j <= n; ++j) memo[i][j] = v[i] * v[j];
  }
  dp.assign(n + 1, vector<ModInt<>>(n + 1, 0));
  dp[0][0] = 1;
  for (int i = 1; i <= n; ++i) {
    for (int j = 0; j < i; ++j)
      for (int k = j; k < i; ++k)
        if (memo[j][k].t >= 0) {
          dat now = memo[j][k] * v[i];
          if (now.t < 0) continue;
          if (now == v[i])
            dp[i][i] += dp[j][k];
          else if (now == memo[j][i])
            dp[j][i] += dp[j][k];
          else if (now == memo[k][i])
            dp[k][i] += dp[j][k];
          else
            assert(0);
        }
  }
  ModInt<> res = -1;
  for (int i = 0; i <= n; ++i)
    for (int j = i; j <= n; ++j) res += dp[i][j];
  return res;
}
accuracy: 0.02564102564102564
time_ms: 10
memory_kb: 4768
final_rank: 16

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

template <int mod = (int)(998244353)>
struct ModInt {
  int x;
  constexpr ModInt() : x(0) {}
  constexpr ModInt(int64_t y)
      : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  constexpr ModInt &operator+=(const ModInt &p) noexcept {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &p) noexcept {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &p) noexcept {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  constexpr ModInt &operator/=(const ModInt &p) noexcept {
    *this *= p.inverse();
    return *this;
  }
  constexpr ModInt operator-() const { return ModInt(-x); }
  constexpr ModInt operator+(const ModInt &p) const noexcept {
    return ModInt(*this) += p;
  }
  constexpr ModInt operator-(const ModInt &p) const noexcept {
    return ModInt(*this) -= p;
  }
  constexpr ModInt operator*(const ModInt &p) const noexcept {
    return ModInt(*this) *= p;
  }
  constexpr ModInt operator/(const ModInt &p) const noexcept {
    return ModInt(*this) /= p;
  }
  constexpr bool operator==(const ModInt &p) const noexcept { return x == p.x; }
  constexpr bool operator!=(const ModInt &p) const noexcept { return x != p.x; }
  constexpr ModInt inverse() const noexcept {
    int a = x, b = mod, u = 1, v = 0, t = 0;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  constexpr ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while (n) {
      if (n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend constexpr ostream &operator<<(ostream &os, const ModInt &p) noexcept {
    return os << p.x;
  }
  friend constexpr istream &operator>>(istream &is, ModInt &a) noexcept {
    int64_t t = 0;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  constexpr int get_mod() { return mod; }
};

struct dat {
  int t, l, r;
  dat(int x = 0, int y = 0, int z = 0) : t(x), l(y), r(z) {}
  bool operator==(const dat &d) const {
    return t == d.t && l == d.l && r == d.r;
  }
  dat operator*(const dat &d) const {
    if (t < 0) return dat(-1, 0, 0);
    dat res(d.t, max(d.l, l - (d.t - t)), min(d.r, r + (d.t - t)));
    if (res.l > res.r || res.r < d.l || d.r < res.l) res = dat(-1, 0, 0);
    return res;
  }
};

int n;
vector<dat> v;
vector<vector<dat>> memo;
vector<vector<ModInt<>>> dp;

ModInt<> solve();

int main() {
  cin >> n;
  v.resize(n + 1);
  for (int i = 1; i <= n; ++i) cin >> v[i].t >> v[i].l >> v[i].r;
  cout << solve() << endl;
  return 0;
}

ModInt<> solve() {
  {  // pre calc
    memo.resize(n + 1, vector<dat>(n + 1));
    for (int i = 0; i <= n; ++i)
      for (int j = i; j <= n; ++j) memo[i][j] = v[i] * v[j];
  }
  dp.assign(n + 1, vector<ModInt<>>(n + 1, 0));
  dp[0][0] = 1;
  for (int i = 1; i <= n; ++i) {
    for (int j = 0; j < i; ++j)
      for (int k = j; k < i; ++k)
        if (memo[j][k].t >= 0) {
          dat now = memo[j][k] * v[i];
          if (now.t < 0) continue;
          if (now == v[i])
            dp[i][i] += dp[j][k];
          else if (now == memo[j][i])
            dp[j][i] += dp[j][k];
          else
            dp[k][i] += dp[j][k];
        }
  }
  ModInt<> res = -1;
  for (int i = 0; i <= n; ++i)
    for (int j = i; j <= n; ++j) res += dp[i][j];
  return res;
}
accuracy: 0.02564102564102564
time_ms: 20
memory_kb: 4884
final_rank: 18

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

template <int mod = (int)(998244353)>
struct ModInt {
  int x;
  constexpr ModInt() : x(0) {}
  constexpr ModInt(int64_t y)
      : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  constexpr ModInt &operator+=(const ModInt &p) noexcept {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &p) noexcept {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &p) noexcept {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  constexpr ModInt &operator/=(const ModInt &p) noexcept {
    *this *= p.inverse();
    return *this;
  }
  constexpr ModInt operator-() const { return ModInt(-x); }
  constexpr ModInt operator+(const ModInt &p) const noexcept {
    return ModInt(*this) += p;
  }
  constexpr ModInt operator-(const ModInt &p) const noexcept {
    return ModInt(*this) -= p;
  }
  constexpr ModInt operator*(const ModInt &p) const noexcept {
    return ModInt(*this) *= p;
  }
  constexpr ModInt operator/(const ModInt &p) const noexcept {
    return ModInt(*this) /= p;
  }
  constexpr bool operator==(const ModInt &p) const noexcept { return x == p.x; }
  constexpr bool operator!=(const ModInt &p) const noexcept { return x != p.x; }
  constexpr ModInt inverse() const noexcept {
    int a = x, b = mod, u = 1, v = 0, t = 0;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  constexpr ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while (n) {
      if (n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend constexpr ostream &operator<<(ostream &os, const ModInt &p) noexcept {
    return os << p.x;
  }
  friend constexpr istream &operator>>(istream &is, ModInt &a) noexcept {
    int64_t t = 0;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  constexpr int get_mod() { return mod; }
};

struct dat {
  int t, l, r;
  dat(int x = 0, int y = 0, int z = 0) : t(x), l(y), r(z) {}
  bool operator==(const dat &d) const {
    return t == d.t && l == d.l && r == d.r;
  }
  dat operator*(const dat &d) const {
    if (t < 0) return dat(-1, 0, 0);
    dat res(d.t, max(d.l, l - (d.t - t)), min(d.r, r + (d.t - t)));
    if (res.l > res.r || res.r < d.l || d.r < res.l) res = dat(-1, 0, 0);
    return res;
  }
};

int n;
vector<dat> v;
vector<vector<dat>> memo;
vector<vector<vector<ModInt<>>>> dp;

ModInt<> solve();

int main() {
  cin >> n;
  v.resize(n + 1);
  for (int i = 1; i <= n; ++i) cin >> v[i].t >> v[i].l >> v[i].r;
  cout << solve() << endl;
  return 0;
}

ModInt<> solve() {
  {  // pre calc
    memo.resize(n + 1, vector<dat>(n + 1));
    for (int i = 0; i <= n; ++i)
      for (int j = i; j <= n; ++j) memo[i][j] = v[i] * v[j];
  }
  dp.assign(n + 1, vector(n + 1, vector<ModInt<>>(n + 1, 0)));
  dp[0][0][0] = 1;
  for (int i = 1; i <= n; ++i) {
    dp[i] = dp[i - 1];
    for (int j = 0; j < i; ++j)
      for (int k = j; k < i; ++k) {
        dat now = memo[j][k] * v[i];
        if (now.t < 0) continue;
        if (now == v[i])
          dp[i][i][i] += dp[i - 1][j][k];
        else
          dp[i][j][i] += dp[i - 1][j][k];
      }
  }
  ModInt<> res = -1;
  for (int i = 0; i <= n; ++i)
    for (int j = i; j <= n; ++j) res += dp[n][i][j];
  return res;
}
accuracy: 0.02564102564102564
time_ms: 60
memory_kb: 114152
final_rank: 20

code_snippet: #include <iostream>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <cassert>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <string>
#include <algorithm>
#include <utility>
#define llint long long
#define inf 1e18
#define PI 3.14159265358979323846264338327950
#define eps 1e-8
#define rep(x, s, t) for(llint (x) = (s); (x) < (t); (x)++)
#define Rep(x, s, t) for(llint (x) = (s); (x) <= (t); (x)++)
#define chmin(x, y) (x) = min((x), (y))
#define chmax(x, y) (x) = max((x), (y))
#define mod 998244353

using namespace std;
typedef pair<llint, llint> P;

llint n;
llint t[305], l[305], r[305];
llint dp[305][305][305];

int main(void)
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	cin >> n;
	for(int i = 1; i <= n; i++) cin >> t[i] >> l[i] >> r[i];
	
	dp[0][0][0] = 1;
	for(int i = 0; i < n; i++){
		for(int j = 0; j <= n; j++){
			for(int k = 0; k <= n; k++){
				(dp[i+1][j][k] += dp[i][j][k]) %= mod;
				llint nj = j, nk = k;
				llint L = l[j] - (t[i+1] - t[j]), R = r[k] + (t[i+1] - t[k]);
				if(R < l[i+1] || L > r[i+1]) continue;
				if(L <= l[i+1]) nj = i+1;
				if(R >= r[i+1]) nk = i+1;
				(dp[i+1][nj][nk] += dp[i][j][k]) %= mod;
			}
		}
	}
	
	llint ans = 0;
	for(int j = 0; j <= n; j++){
		for(int k = 0; k <= n; k++){
			ans += dp[n][j][k], ans %= mod;
		}
	}
	ans += mod - 1, ans %= mod;
	cout << ans << endl;
	
	return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 219556
final_rank: 11

code_snippet: #include <iostream>
#include <map>
#include <vector>

template <int MOD>
struct ModInt {
    using lint = long long;
    int val;

    // constructor
    ModInt(lint v = 0) : val(v % MOD) {
        if (val < 0) val += MOD;
    };

    // unary operator
    ModInt operator+() const { return ModInt(val); }
    ModInt operator-() const { return ModInt(MOD - val); }
    ModInt inv() const { return this->pow(MOD - 2); }

    // arithmetic
    ModInt operator+(const ModInt& x) const { return ModInt(*this) += x; }
    ModInt operator-(const ModInt& x) const { return ModInt(*this) -= x; }
    ModInt operator*(const ModInt& x) const { return ModInt(*this) *= x; }
    ModInt operator/(const ModInt& x) const { return ModInt(*this) /= x; }
    ModInt pow(lint n) const {
        auto x = ModInt(1);
        auto b = *this;
        while (n > 0) {
            if (n & 1) x *= b;
            n >>= 1;
            b *= b;
        }
        return x;
    }

    // compound assignment
    ModInt& operator+=(const ModInt& x) {
        if ((val += x.val) >= MOD) val -= MOD;
        return *this;
    }
    ModInt& operator-=(const ModInt& x) {
        if ((val -= x.val) < 0) val += MOD;
        return *this;
    }
    ModInt& operator*=(const ModInt& x) {
        val = lint(val) * x.val % MOD;
        return *this;
    }
    ModInt& operator/=(const ModInt& x) { return *this *= x.inv(); }

    // compare
    bool operator==(const ModInt& b) const { return val == b.val; }
    bool operator!=(const ModInt& b) const { return val != b.val; }
    bool operator<(const ModInt& b) const { return val < b.val; }
    bool operator<=(const ModInt& b) const { return val <= b.val; }
    bool operator>(const ModInt& b) const { return val > b.val; }
    bool operator>=(const ModInt& b) const { return val >= b.val; }

    // I/O
    friend std::istream& operator>>(std::istream& is, ModInt& x) noexcept {
        lint v;
        is >> v;
        x = v;
        return is;
    }
    friend std::ostream& operator<<(std::ostream& os, const ModInt& x) noexcept { return os << x.val; }
};

constexpr int MOD = 998244353;
using mint = ModInt<MOD>;

void solve() {
    int n;
    std::cin >> n;

    std::map<std::pair<int, int>, mint> dp;
    dp[std::make_pair(0, 0)] = 1;

    int pt = 0;
    while (n--) {
        int t, l, r;
        std::cin >> t >> l >> r;

        std::map<std::pair<int, int>, mint> ndp;
        for (auto [p, v] : dp) {
            auto [pl, pr] = p;

            pl -= t - pt;
            pr += t - pt;

            {
                auto q = std::make_pair(pl, pr);
                if (!ndp.count(q)) ndp[q] = 0;
                ndp[q] += v;
            }

            pl = std::max(pl, l);
            pr = std::min(pr, r);
            if (pr < pl) continue;

            {
                auto q = std::make_pair(pl, pr);
                if (!ndp.count(q)) ndp[q] = 0;
                ndp[q] += v;
            }
        }

        std::swap(dp, ndp);
        pt = t;
    }

    mint ans = 0;
    for (auto [p, v] : dp) ans += v;
    std::cout << ans - 1 << "\n";
}

int main() {
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 4472
final_rank: 6