#include <iostream> // cin, cout, cerr
#include <algorithm> // minmax, sort, swap
#include <numeric> // iota
#include <cstdio> // printf, scanf
#include <string> // string, stoi, to_string
#include <vector> // vector
#include <queue> // queue, priority_queue
#include <deque> // deque
#include <map> // key-value pairs sorted by keys
#include <set> // set
#include <iomanip> // cout<<setprecision(n)
#include <functional> // function<void(int)>
#include <cmath>

#ifdef DEBUG
#include "debug.hpp"
#else
#define debug(...)
#endif

#define int long long // at least int64 > 9*10^18
#define ENDL '\n'
#define rep(i,n) for(int i = 0; i < (n); i++)
#define print(i) std::cout << (i) << '\n'
#define all(v) (v).begin(), (v).end()
/* libraries */

const int INF = 1e9;

struct S
{
	int x;
	S() {}
	S(int x) : x(x) {}
	static S I() {
		return S(INF);
	}
	void merge(S& a, S& b) {
		x = std::min(a.x,b.x);
	}
};

struct SegmentTree
{
	const int n;
	std::vector<S> data;
	SegmentTree(int n, std::vector<int>& a) : n(n), data(2*n) {
		for(int i=0;i<n;i++) {
			data[n+i] = S(a[i]);
		}
		for(int i=n-1;i>0;i--) {
			data[i].merge(data[i<<1], data[i<<1|1]);
		}
	}
	void set(int i, S v) {
		data[n+i] = v;
		i+=n;
		while(i>0) {
			i>>=1;
			data[i].merge(data[i<<1], data[i<<1|1]);
		}
	}
	S get(int l, int r) {
		// 0-Indexed, [l, r)
		l+=n; r+=n;
		S sum = S::I();
		while(l<r) {
			if(l&1) sum.merge(sum,data[l++]);
			if(r&1) sum.merge(sum,data[--r]);
			l>>=1; r>>=1;
		}
		return sum;
	}
};


constexpr int MOD = 998244353;
struct mint
{
	int v;
	mint():v(0){}
	mint(int v):v((v+MOD)%MOD){}
	mint operator-()const{ return mint(0) - *this; }
	mint& operator+=(const mint& a){ if((v+=a.v)>=MOD) v-=MOD; return *this; }
	mint& operator-=(const mint& a){ if((v+=MOD-a.v)>=MOD) v-=MOD; return *this; }
	mint& operator*=(const mint& a){ (v*=a.v)%=MOD; return *this; }
	mint& operator/=(const mint& a){ (*this) *= a.inv(); return *this; }
	mint operator+(const mint& a)const{ return mint(*this) += a; }
	mint operator-(const mint& a)const{ return mint(*this) -= a; }
	mint operator*(const mint& a)const{ return mint(*this) *= a; }
	mint operator/(const mint& a)const{ return mint(*this) /= a; }
	bool operator<(const mint& a)const{ return v < a.v; }
	bool operator==(const mint& a)const{ return v == a.v; }
	mint pow(int k)const{ mint r(1),t(v); while(k){ if(k&1) r*=t; t*=t; k>>=1; } return r; }
	mint inv()const{ return pow(MOD-2); }
	static mint comb(int n, int k) {
		if(n-k<k) k=n-k;
		mint num(1), dom(1);
		for(int i=0;i<k;i++) { num*=n-i; dom*=i+1; }
		return num/dom;
	}
};
std::istream& operator>>(std::istream&i,mint&a){ int t; i>>t; a=mint(t); return i; }
std::ostream& operator<<(std::ostream&o,const mint&a){ o<<a.v; return o; }

signed main() {
	int n;
	std::cin >> n;
	std::vector<std::pair<int,int> > robots;
	rep(i,n) {
		int x,d;
		std::cin >> x >> d;
		robots.emplace_back(x,d);
	}
	std::sort(all(robots),std::greater<>());
	std::vector<int> too(n);
	std::iota(all(too),0);
	SegmentTree to(n,too);
	rep(i,n) {
		int l=-1,r=n;
		while(r-l>1) {
			int mid = (l+r)/2;
			int xx = robots[i].first+robots[i].second;
			if(robots[mid].first>=xx) l=mid;
			else r=mid;
		}
		debug(i,r);
		to.set(i,to.get(r,i+1));
	}
	std::vector<std::vector<mint> > dp(n,std::vector<mint>(2));
	dp[0][0]=1;
	dp[0][1]=1;
	for(int i=1;i<n;i++) {
		dp[i][0] = dp[i-1][0]+dp[i-1][1];
		dp[i][1] = dp[i-1][0]+dp[i-1][1];
		dp[i][1] = dp[to.get(i,i+1).x][1];
	}
	// for(auto x:robots) std::cout << x.first << ' ' << x.second << '\n';
	debug(dp);
	print(dp[n-1][0]+dp[n-1][1]);
	return 0;
}


Measured memory_bytes: 19948