#include <bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < (int)(n); i ++)
#define irep(i,n) for (int i = (int)n - 1;i >= 0;--i)
using namespace std;
using ll = long long;
using PL = pair<ll,ll>;
using P = pair<int,int>;
constexpr int INF = 1000000000;
constexpr long long HINF = 1000000000000000;
constexpr long long MOD = 1000000007;// = 998244353;
constexpr double EPS = 1e-4;
constexpr double PI = 3.14159265358979;
const int dy[4] = {1,0,-1,0};
const int dx[4] = {0,1,0,-1};

template<int Modulus> 
struct ModInt {
    long long x;
    ModInt(long long x = 0) :x((x%Modulus + Modulus)%Modulus) {}
    constexpr ModInt &operator+=(const ModInt a) {if ((x += a.x) >= Modulus) x -= Modulus; return *this;}
    constexpr ModInt &operator-=(const ModInt a) {if ((x += Modulus - a.x) >= Modulus) x -= Modulus; return *this;}
    constexpr ModInt &operator*=(const ModInt a) {(x *= a.x) %= Modulus; return *this;}
    constexpr ModInt &operator/=(const ModInt a) {return *this *= a.inverse();}

    constexpr ModInt operator+(const ModInt a) const {return ModInt(*this) += a.x;}
    constexpr ModInt operator-(const ModInt a) const {return ModInt(*this) -= a.x;}
    constexpr ModInt operator*(const ModInt a) const {return ModInt(*this) *= a.x;}
    constexpr ModInt operator/(const ModInt a) const {return ModInt(*this) /= a.x;}
    
    friend constexpr ostream& operator<<(ostream& os,const ModInt<Modulus>& a) {return os << a.x;}
    friend constexpr istream& operator>>(istream& is,ModInt<Modulus>& a) {return is >> a.x;}
    
    ModInt inverse() const {// x ^ (-1) 
        long long a = x,b = Modulus,p = 1,q = 0;
        while (b) {long long d = a/b; a -= d*b; swap(a,b); p -= d*q; swap(p,q);}
        return ModInt(p);
    }
    ModInt pow(long long N) {// x ^ N 
        ModInt a = 1;
        while (N) {
            if (N&1) a *= *this;
            *this *= *this;
            N >>= 1;
        }
        return a;
    }
};

using mint = ModInt<998244353>;

template<class Monoid> struct SegmentTree{
    int N;
    vector<Monoid> tree;

    //depending on the problem
    Monoid unit;
    using FX = function<Monoid(Monoid,Monoid)>; FX func;
    //

    SegmentTree(int _N,Monoid _unit,FX _func) :N(_N),unit(_unit),func(_func) {
        tree.assign(2*N,unit);
    }

    void build(){
        for (int i = N; i < 2*N; i++) tree[i] = i - N;
        for (int i = N - 1;i > 0; i--) tree[i] = func(tree[i << 1],tree[i << 1|1]);
    }

    void update(int k,Monoid x){
        k += N;
        tree[k] = func(tree[k],x);
        while (k > 1){
            k >>= 1;
            tree[k] = func(tree[k << 1],tree[k << 1|1]);
        }
    }

    Monoid query(int L,int R){
        L += N; R += N;
        Monoid vL = unit,vR = unit;
        while (L < R){
            if (L&1){ vL = func(vL,tree[L]); L ++; }
            if (R&1){ R --; vR = func(tree[R],vR); }
            L >>= 1; R >>= 1;
        }
        return func(vL,vR);
    }

    void debug() {
        for (int i = 0;i < 2*N;++i) cout << "  st[" << i << "] : " << tree[i];
    }
};

int main() {
    int N; cin >> N;
    vector<P> robot(N);
    rep(i,N) cin >> robot[i].first >> robot[i].second;
    sort(robot.begin(),robot.end());
    vector<int> X(N),D(N);
    rep(i,N) {
        X[i] = robot[i].first;
        D[i] = robot[i].second;
    }
    //
    auto f = [](ll a,ll b){return max(a,b);};
    SegmentTree<int> st(N,0,f);
    st.build();
    //
    vector<mint> dp(N + 1);
    dp[N] = 1;
    irep(i,N) {
        dp[i] = dp[i + 1];
        int r = lower_bound(X.begin(),X.end(),X[i] + D[i]) - X.begin();
        int x = st.query(i,r);
        dp[i] += dp[x + 1];
        st.update(i,x);
    }
    cout << dp[0] << '\n';
    return 0;
}

Measured memory_bytes: 9592