#include <iostream>
#include <iomanip>
#include <vector>
#include <unordered_map>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <array>
#include <tuple>
#include <string>
#include <algorithm>
#include <functional>
#include <cmath>
#include <numeric>
#include <bitset>
#include <cstdint>
using namespace std;

#ifdef DEBUG
#include <cassert>
#else
#define assert(x)
#endif

#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, a, b) for (int i = (a); i < (int)(b); i++)
using ll = long long;

//////////////// //////////////// //////////////// //////////////// ////////////////
//////////////// //////////////// //////////////// //////////////// ////////////////

struct intvl
{
    int l;
    int r;
};

template <typename M>
struct seg_tree
{
    int n;
    using T = typename M::T;

private:
    vector<T> data;

    vector<intvl> intvl_s;

    // ノードの端点を得る
    intvl intvl_of_node(int i)
    {
        return intvl_s[i];
    }

    // (2ベキでないときに出てくる)不要なノードならfalse
    bool is_valid_node(int i)
    {
        intvl lr = intvl_of_node(i);
        return lr.l < lr.r;
    }

    // ノードから区間の端点への対応を前計算
    void init_intvl_s()
    {
        rep(i, n)
        {
            intvl_s[n + i] = {i, i + 1};
        }
        for (int i = n - 1; i >= 1; i--)
        {
            intvl_s[i] = {intvl_s[2 * i].l, intvl_s[2 * i + 1].r};
        }
    }

public:
    // idで初期化
    seg_tree(int size)
        : n(size), data(2 * size, M::id), intvl_s(2 * size)
    {
        init_intvl_s();
    }

    // a_sで初期化
    seg_tree(int size, vector<T> a_s)
        : n(size), data(2 * size), intvl_s(2 * size)
    {
        rep(i, n)
        {
            data[n + i] = a_s[i];
        }
        for (int i = n - 1; i >= 1; i--)
        {
            if (not is_valid_node(i))
            {
                continue;
            }
            data[i] = M::op(data[2 * i], data[2 * i + 1]);
        }

        init_intvl_s();
    }

    // i番目をaに変更
    void update(int i, int a)
    {
        i += n;
        data[i] = a;
        while (i > 1)
        {
            i /= 2;
            if (not is_valid_node(i))
            {
                break;
            }
            data[i] = M::op(data[2 * i], data[2 * i + 1]);
        }
    }

    // [l,r) の取得
    T sum(intvl lr)
    {
        int l = lr.l, r = lr.r;
        l += n;
        r += n;
        T retl = M::id, retr = M::id;
        while (l < r)
        {
            if (l & 1)
            {
                retl = M::op(retl, data[l]);
                ++l;
            }
            if (r & 1)
            {
                --r;
                retr = M::op(data[r], retr);
            }
            l /= 2;
            r /= 2;
        }
        return M::op(retl, retr);
    }

    // iの取得
    T at(int i)
    {
        return data[i + n];
    }
};

constexpr int mod = 998244353;

struct mon
{
    using T = int;
    static T op(T a, T b)
    {
        return max(a, b);
    }
    static inline int id = 0;
};

int main()
{
    // 高速な入出力
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    // 浮動小数の表示の精度
    cout << setprecision(15);

    int n;
    cin >> n;

    vector<pair<int, int>> xd_s(n);
    rep(i, n)
    {
        int x, d;
        cin >> x >> d;
        xd_s[i] = {x, d};
    }
    sort(xd_s.begin(), xd_s.end());
    vector<int> x_s(n), d_s(n);
    rep(i, n)
    {
        x_s[i] = xd_s[i].first;
        d_s[i] = xd_s[i].second;
    }

    rep(i, n)
    {
        d_s[i] = lower_bound(x_s.begin(), x_s.end(), x_s[i] + d_s[i]) - x_s.begin() - i;
    }

    seg_tree<mon> r_s(n);
    for (int i = n - 1; i >= 0; --i)
    {
        r_s.update(i, max(i, r_s.sum({i + 1, i + d_s[i]})));
    }

    vector<int> dp(n + 1);
    dp[n] = 1;
    for (int i = n - 1; i >= 0; --i)
    {
        dp[i] = (dp[i + 1] + dp[r_s.at(i) + 1]) % mod;
    }

    cout << dp[0] << endl;

    return 0;
}


Measured memory_bytes: 11912