#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>

using namespace std;
using ll = long long;
using pii = pair<ll, ll>;

#define rep(i,n) for(int i=0;i<(n);++i)
#define all(f,c,...) (([&](decltype((c)) cccc) { return (f)(begin(cccc), end(cccc), ## __VA_ARGS__); })(c))

#define rrep(i,n) for(int i=(n);i>=0;--i)
const int MOD = 998244353;



template<int MOD> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MOD) { if (val < 0) val += MOD; }
    constexpr int getmod() { return MOD; }
    constexpr Fp operator - () const noexcept { return val ? MOD - val : 0; }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, 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);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept { return this->val == r.val; }
    constexpr bool operator != (const Fp& r) const noexcept { return this->val != r.val; }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept { return os << x.val; }
    friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(a, n / 2);
        t = t * t;
        if (n & 1) t = t * a;
        return t;
    }
};

using mint = Fp<MOD>;

template<typename T>struct SegTree {
  private:
    using F = function<T(T,T)>;
    int n;
    vector<T> node;
    const F f;
    const T init;
  public:
    SegTree(int size, T init, const F f) : init(init), f(f) {
      n = 1;
      while (n < size) n *= 2;
      node.resize(2*n-1, init);
    }
    void update(int index, T value) {
      index = n - 1 + index;
      node[index] = value;
      while (index != 0) {
        index = (index-1) / 2;
        node[index] = f(node[2*index+1], node[2*index+2]);
      }
    }
    T query(int left, int right, int k = 0, int l = 0, int r = -1) {
      if (r < 0) r = n;
      if (r <= left || right <= l) return init;
      if (left <= l && r <= right) return node[k];
      return f(query(left, right, 2*k+1, l, (l+r)/2), query(left, right, 2*k+2, (l+r)/2, r));
    }
};

int main() {
  int N; cin >> N;

  vector<pii> robot(N+1);
  rep(i, N) {
    cin >> robot[i].first >> robot[i].second;
  }
  robot[N].first = 2e9+1;
  robot[N].second = 1;
  all(sort, robot);

  vector<mint> dp(N+1, 0); // dp[i] = ロボットiのスイッチを入れたときの場合の数
  vector<mint> dp2(N+1, 0); // dp[i] = ロボットiのスイッチを入れないときの場合の数
  vector<int> right(N+1, 0); // right[i] = ロボットiのスイッチを入れたときに動くもっとも右にある要素のインデックス

  SegTree<int> T(N, 0, [](int a, int b){return max(a, b);});

  dp[N] = 1;
  dp2[N] = 0;
  right[N] = 0;
  rrep(i, N-1) {
    // robot[i].first + robot[i].second以上になるものを探したい
    auto it = all(lower_bound, robot, pii(robot[i].first + robot[i].second, 0));
    int j = it - robot.begin(); // iが接触しないロボットのうち左端のもの
    if (j == i+1) {
      right[i] = i;
      dp[i] = dp[i+1] + dp2[i+1];
    } else {
      right[i] = T.query(i+1, j);
      dp[i] = dp[right[i]+1] + dp2[right[i]+1];
    }
    T.update(i, right[i]);

    dp2[i] = dp[i+1] + dp2[i+1];
  }
  cout << dp[0] + dp2[0] << endl;

  return 0;
}


Measured memory_bytes: 9344