#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <unordered_map>
#include <set>
#include <functional>
#include <bitset>
#include <numeric>
#include <cassert>
#include <random>
using namespace std;
using ll = long long;


// Modint
struct Mint {
	static const ll mod = 998244353;
	ll val;

	Mint() { val = 0; }
	Mint(ll a) { val = a; verify_value(); }

	void verify_value() {
		if (val >= mod) val %= mod;
		if (val < 0) val %= mod, val += mod;
	}

	Mint pow(ll p) const {
		Mint cur = Mint(val), ret = 1;
		while (p > 0) {
			if (p & 1) ret *= cur;
			cur *= cur;
			p >>= 1LL;
		}
		return ret;
	}
	Mint inv() const {
		if (val == 0) cerr << "WARNING: inv() is called with 0." << endl;
		return pow(mod - 2);
	}

	Mint operator+() const { return *this; }
	Mint operator-() const { return Mint(mod - val); }

	Mint operator+=(const Mint &a) {
		val += a.val;
		if (val >= mod) val -= mod;
		return Mint(val);
	}
	Mint operator*=(const Mint &a) {
		val *= a.val;
		if (val >= mod) val %= mod;
		return Mint(val);
	}
	Mint operator-=(const Mint &a) { return *this += -a; }
	Mint operator/=(const Mint &a) { return *this *= a.inv(); }

	Mint operator++() { return *this += Mint(1); }
	Mint operator--() { return *this -= Mint(1); }
	Mint operator++(int) {
		Mint ret = *this;
		++(*this);
		return ret;
	}
	Mint operator--(int) {
		Mint ret = *this;
		--(*this);
		return ret;
	}

	operator ll() const { return val; }
};

Mint operator+(const Mint &a, const Mint &b) {
	ll ret = a.val + b.val;
	if (ret >= Mint::mod) ret -= Mint::mod;
	return Mint(ret);
}
Mint operator*(const Mint &a, const Mint &b) {
	ll ret = a.val * b.val;
	if (ret >= Mint::mod) ret %= Mint::mod;
	return Mint(ret);
}
Mint operator-(const Mint &a, const Mint &b) { return a + (-b); }
Mint operator/(const Mint &a, const Mint &b) { return a * b.inv(); }

ostream &operator<<(ostream &out, const Mint &a) { return out << a.val; }
istream &operator>>(istream &in, Mint &a) {
	in >> a.val;
	a.verify_value();
	return in;
}


class SegmentTree {
private:
	using Monoid = int;
	const Monoid INI = -1;
	Monoid op(Monoid a, Monoid b) {
		return max(a, b);
	}

	int num;
	vector<Monoid> dat;

public:
	SegmentTree(int n_) {
		num = 1;
		while (num < n_) num *= 2;
		dat = vector<Monoid>(2 * num, INI);
	}

	SegmentTree(const vector<Monoid> &m) : SegmentTree(m.size()) {
		int n = m.size();
		for (int i = 0; i < n; i++) {
			dat[num - 1 + i] = m[i];
		}
		for (int i = num - 2; i >= 0; i--) {
			dat[i] = op(dat[2 * i + 1], dat[2 * i + 2]);
		}
	}

	// Update the k-th value (0-indexed) to a.
	void update(int k, Monoid a) {
		k += num - 1;
		dat[k] = a;
		while (k > 0) {
			k = (k - 1) / 2;
			dat[k] = op(dat[2 * k + 1], dat[2 * k + 2]);
		}
	}

	// Get the value of the range [a, b).
	// k: The index of the node.
	// [left, right): The range corresponds to the k-th node.
	// Call like getval(a, b).
	Monoid getval(int a, int b, int k = 0, int left = 0, int right = -1) {
		if (right < 0) right = num;
		if (right <= a || b <= left) return INI;
		if (a <= left && right <= b) return dat[k];
		Monoid vleft = getval(a, b, 2 * k + 1, left, left + (right - left) / 2);
		Monoid vright = getval(a, b, 2 * k + 2, left + (right - left) / 2, right);
		return op(vleft, vright);
	}
};

int main() {
	int n; cin >> n;
	vector<pair<int, int>> xd(n);
	for (int i = 0; i < n; i++) {
		cin >> xd[i].first >> xd[i].second;
	}
	xd.emplace_back(2e9 + 1, 2e9 + 1);
	sort(xd.begin(), xd.end());
	vector<int> x(n), d(n);
	for (int i = 0; i < n; i++) {
		tie(x[i], d[i]) = xd[i];
	}
	vector<int> t(n + 2);
	iota(t.begin(), t.end(), 1);
	SegmentTree to(t);
	for (int i = n - 2; i >= 0; i--) {
		auto iter = lower_bound(x.begin(), x.end(), x[i] + d[i]);
		int t = iter - x.begin();
		int v = to.getval(i, t);
		to.update(i, v);
	}
	vector<Mint> dp(n + 2);
	dp[0] = 1;
	for (int i = 0; i < n; i++) {
		dp[i + 1] += dp[i];
		dp[to.getval(i, i + 1)] += dp[i];
	}
	cout << dp[n] << endl;
	return 0;
}


Measured memory_bytes: 9060