#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (int)(n); ++i)
#define all(x) x.begin(),x.end()
#define ln '\n'
//const long long MOD = 1000000007LL;
const long long MOD = 998244353LL;
typedef long long ll;
typedef unsigned long long ull; 
typedef pair<int, int> pii;
typedef pair<long long, long long> pll;
template<class T> inline bool chmax(T &a, T b) { if (a < b) { a = b; return true;} return false; }
template<class T> inline bool chmin(T &a, T b) { if (a > b) { a = b; return true;} return false; }
///////////////////////////////////////////////////////////////////////////////////////////////////

template <std::uint_fast64_t Modulus> class modint {
  using u64 = std::uint_fast64_t;

public:
  u64 a;

  constexpr modint(const u64 x = 0) noexcept : a(x % Modulus) {}
  constexpr u64 &value() noexcept { return a; }
  constexpr const u64 &value() const noexcept { return a; }
  constexpr modint operator+(const modint rhs) const noexcept {
    return modint(*this) += rhs;
  }
  constexpr modint operator-(const modint rhs) const noexcept {
    return modint(*this) -= rhs;
  }
  constexpr modint operator*(const modint rhs) const noexcept {
    return modint(*this) *= rhs;
  }
  constexpr modint operator/(const modint rhs) const noexcept {
    return modint(*this) /= rhs;
  }
  constexpr modint &operator+=(const modint rhs) noexcept {
    a += rhs.a;
    if (a >= Modulus) {
      a -= Modulus;
    }
    return *this;
  }
  constexpr modint &operator-=(const modint rhs) noexcept {
    if (a < rhs.a) {
      a += Modulus;
    }
    a -= rhs.a;
    return *this;
  }
  constexpr modint &operator*=(const modint rhs) noexcept {
    a = a * rhs.a % Modulus;
    return *this;
  }
  constexpr modint &operator/=(modint rhs) noexcept {
    u64 exp = Modulus - 2;
    while (exp) {
      if (exp % 2) {
        *this *= rhs;
      }
      rhs *= rhs;
      exp /= 2;
    }
    return *this;
  }
};

using mint = modint<MOD>;

template<typename T>
struct Compress {
  vector<T> xs;

  Compress() = default;

  Compress(const vector<T> &vs) {
    add(vs);
  }

  Compress(const initializer_list<vector<T>> &vs) {
    for(auto &p : vs) add(p);
  }

  void add(const vector<T> &vs) {
    copy(begin(vs), end(vs), back_inserter(xs));
  }

  void add(const T &x) {
    xs.emplace_back(x);
  }

  void build() {
    sort(begin(xs), end(xs));
    xs.erase(unique(begin(xs), end(xs)), end(xs));
  }

  vector<int> get(const vector<T> &vs) const {
    vector<int> ret;
    transform(begin(vs), end(vs), back_inserter(ret), [&](const T &x) {
      return lower_bound(begin(xs), end(xs), x) - begin(xs);
    });
    return ret;
  }

  int get(const T &x) const {
    return lower_bound(begin(xs), end(xs), x) - begin(xs);
  }

  const T &operator[](int k) const {
    return xs[k];
  }
};


template<typename T, typename Monoid>
struct SegmentTree {
    T unity;
    Monoid merge;
    int N;
    vector<T> node;

    SegmentTree(Monoid f, T id) : merge(f), unity(id) {}

    void init(int sz) {
        N = 1;
        while (N < sz) N *= 2;
        node.assign(2*N,unity);
    }

    void set(int k, const T &val) {node[k+N] = val;}

    void build() {
        for (int i = N-1; i > 0; --i) {
            node[i] = merge(node[i<<1|0], node[i<<1|1]);
        }
    }

    // (0-indexed)
    void update(int x, T val) {
        x += N;
        node[x] = val;
        while (x > 1) {
            x >>= 1;
            node[x] = merge(node[x<<1|0], node[x<<1|1]);
        }
    }

    // [l, r) (0-indexed)
    T get(int l, int r) {
        T resl = unity, resr = unity;
        l += N; r += N;
        while (l < r) {
            if (l & 1) resl = merge(resl, node[l++]);
            l >>= 1;
            if (r & 1) resr = merge(node[--r], resr);
            r >>= 1;
        }
        return merge(resl, resr);
    }

    T operator[](int x) {return node[x+N];}
};

/*
example
auto f=[&](int a,int b){return max(a,b);};
const int id = -1e9;
SegmentTree<int, decltype(f)> seg(f,id);
*/

int main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);
    int N; cin >> N;
    vector<ll> X(N),D(N);
    rep(i,N) cin >> X[i] >> D[i];
    
    Compress<ll> Com(X);
    rep(i,N) Com.add(X[i] + D[i]);
    Com.build();
    auto f=[](ll a, ll b) {return max(a,b);};
    const ll id = -1e18;
    SegmentTree<ll, decltype(f)> seg(f,id);
    seg.init(Com.xs.size());
    seg.build();

    vector<pll> A;
    rep(i,N) A.emplace_back(X[i],D[i]);
    sort(all(X));
    sort(all(A));
    reverse(all(A));
    vector<mint> dp(N+1);
    dp[0] = 1;
    rep(i,N) {
        ll x,d;
        tie(x,d) = A[i];
        ll val = max(x+d,seg.get(Com.get(x),Com.get(x+d)));
        int k = lower_bound(all(X),val) - upper_bound(all(X),x);
        dp[i+1] = dp[i] + dp[i-k];
        seg.update(Com.get(x),val);
    }
    
    cout << dp[N].a << ln;
}

Measured memory_bytes: 23148