#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <functional>
#include <vector>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <cassert>
#define InfL 1000000000
#define InfLL 1000000000000000000LL
#define mod 998244353
#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
#define rrep(i,n) for(int (i)=(n-1);(i)>=(0);(i)--)
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<bool> vb;
typedef vector<db> vd;


class SegmentTree {
public:
    int listnum;
    int listnum_pow2 = 1;
    vl node_val;

    void SegmentTree_ini(vl node_val_ini); // 初期化 (ノード更新あり)
    void update(int x, ll val_update); // 1要素の代入 (ノード更新あり)
    ll val_x(int x); // 値の取得
    ll getmin(int search_L, int search_R); // 最小値の取得
    void add(int search_L, int search_R, ll val_add); // 足す (ノード更新あり)
    ll getsum(int search_L, int search_R); // 区間和

private:
    ll getmin_sbrt(int search_L, int search_R, int nodetmp, int L, int R);
    void add_sbrt(int search_L, int search_R, ll val_add, int nodetmp, int L, int R);
    ll getsum_sbrt(int search_L, int search_R, int nodetmp, int L, int R);

};

void SegmentTree::SegmentTree_ini(vl node_val_ini) { // 初期化 (ノード更新あり)
    listnum = node_val_ini.size();
    listnum_pow2 = 1;
    while (listnum_pow2 < listnum)
        listnum_pow2 *= 2;
    for (int i = listnum; i < listnum_pow2; i++) {
        node_val_ini.push_back(InfL); // 最小値
        //node_val_ini.push_back(0); // 和
    }

    node_val.resize(2 * listnum_pow2 - 1);

    for (int i = 0; i < listnum_pow2; i++)
        node_val[i + listnum_pow2 - 1] = node_val_ini[i];
    for (int i = listnum_pow2 - 2; i >= 0; i--) {
        node_val[i] = min(node_val[i * 2 + 1], node_val[i * 2 + 2]); // 最小値
        //node_val[i] = node_val[i * 2 + 1] + node_val[i * 2 + 2]; // 和
    }
}

void SegmentTree::update(int x, ll val_update) { // 1要素の代入 (ノード更新あり)
    int nodetmp = x + listnum_pow2 - 1;
    node_val[nodetmp] = val_update;
    while (nodetmp > 0) {
        nodetmp = (nodetmp - 1) / 2;
        node_val[nodetmp] = min(node_val[2 * nodetmp + 1], node_val[2 * nodetmp + 2]); // 最小値
        //node_val[nodetmp] = node_val[2 * nodetmp + 1] + node_val[2 * nodetmp + 2]; // 和
    }
    return;
}

ll SegmentTree::val_x(int x) { // 値の取得
    int nodetmp = x + listnum_pow2 - 1;
    ll ans = node_val[nodetmp];
    return ans;
}

ll SegmentTree::getmin_sbrt(int search_L, int search_R, int nodetmp, int L, int R) { // 最小値の取得
    if (R <= search_L || search_R <= L)
        return InfL;
    if (search_L <= L && R <= search_R)
        return node_val[nodetmp];

    int M = (L + R) / 2;
    int nodenew_L = 2 * nodetmp + 1;
    ll node_val_min_L = getmin_sbrt(search_L, search_R, nodenew_L, L, M);
    int nodenew_R = 2 * nodetmp + 2;
    ll node_val_min_R = getmin_sbrt(search_L, search_R, nodenew_R, M, R);
    ll node_val_min = min(node_val_min_L, node_val_min_R);
    return node_val_min;
}

ll SegmentTree::getmin(int search_L, int search_R) { // 最小値の取得
    ll ans = getmin_sbrt(search_L, search_R, 0, 0, listnum_pow2);
    return ans;
}

ll SegmentTree::getsum_sbrt(int search_L, int search_R, int nodetmp, int L, int R) { // 区間和
    if (search_R <= L || R <= search_L)
        return 0;
    if (search_L <= L && R <= search_R)
        return node_val[nodetmp];

    int M = (L + R) / 2;
    int nodenew_L = 2 * nodetmp + 1;
    ll node_val_min_L = getsum_sbrt(search_L, search_R, nodenew_L, L, M);
    int nodenew_R = 2 * nodetmp + 2;
    ll node_val_min_R = getsum_sbrt(search_L, search_R, nodenew_R, M, R);
    ll node_val_min = node_val_min_L + node_val_min_R;
    return node_val_min;
}


int main() {
	int N;
	cin >> N;
	vector<pll> XD(N);
	vl DP(N + 1, 0);
    DP[0] = 1;
    SegmentTree Tree;
    vl a;
    rep(i, N)
        a.push_back(i);
    Tree.SegmentTree_ini(a);
	rep(i, N)
		cin >> XD[i].first >> XD[i].second;
	sort(XD.begin(), XD.end(), greater<pll>());
	rep(i, N) {
		ll Xtmp = XD[i].first;
		ll XDtmp = Xtmp + XD[i].second;
		ll L = -1;
		ll R = N;
		while (1) {
			ll M = (L + R + 2) / 2;
            M--;
			if (L == M)
				break;
            if (M == -1)
                break;
			if (XD[M].first < XDtmp)
				R = M;
			else
				L = M;
		}
        L++;
		DP[i + 1] += DP[i];
        int j = Tree.getmin(L, i + 1);
        Tree.update(i, j);
        DP[i + 1] += DP[j];
		DP[i + 1] %= mod;
	}
	cout << DP[N] << endl;
	return 0;
}

Measured memory_bytes: 13524