unittest
{
	assert( [ "2", "1 5", "3 3" ].parse.expand.solve == 3 );
	assert( [ "3", "6 5", "-1 10", "3 3" ].parse.expand.solve == 5 );
	assert( [ "4", "7 10", "-10 3", "4 3", "-4 3" ].parse.expand.solve == 16 );
	assert( [ "20", "-8 1", "26 4", "0 5", "9 1", "19 4", "22 20", "28 27", "11 8", "-3 20", "-25 17", "10 4", "-18 27", "24 28", "-11 19", "2 27", "-2 18", "-1 12", "-24 29", "31 29", "29 7" ].parse.expand.solve == 110 );
	
	assert( ( [ "200000" ].chain( iota( -100000, 100000 ).map!( ( a ) => format( "%s %s", a, 1000000 ) ) ) ).parse.expand.solve == 200001 );		// 追加ケース
}



import std.algorithm;
import std.conv;
import std.format;
import std.range;
import std.stdio;
import std.typecons;

void main()
{
	stdin.byLineCopy.parse.expand.solve.writeln;
}

auto parse( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto n = input.front.to!( long );
	auto xds = new long[ 2 ][ n ];
	foreach( ref xd; xds )
	{
		input.popFront;
		xd = input.front.split.to!( long[] );
	}
	return tuple( xds );
}

auto solve( long[ 2 ][] xds )
{
	const M = 998244353L;
	
	// 各ロボットを起動したときの除外数を計算
	auto rs = new long[ xds.length ];
	{
		auto xds_s = xds.sort();
		auto st = SegmentTree!( max, long.min )( xds.length );
		foreach_reverse( i, xd; xds )
		{
			// 自分の移動距離
			auto dt = xd[ 0 ] + xd[ 1 ];
			
			// 連鎖した各ロボットのうちの最大移動距離
			auto fs = xds_s[ i .. $ ].lowerBound( [ dt, long.min ] );
			auto dm = max( dt, st.query( i, i + fs.length ) );
			st.set( i, dm );
			
			// 最大移動距離で何台除外されるか
			if( dt < dm ) fs = xds_s[ i .. $ ].lowerBound( [ dm, long.min ] );
			rs[ i ] = fs.length;
		}
	}
	
	// dp[ i番目 ] = 通り数
	auto dp = new long[ rs.length + 1 ];
	dp[ 0 ] = 1;
	foreach( i, r; rs )
	{
		dp[ i + 1 ] = ( dp[ i + 1 ] + dp[ i ] ) % M;		// 起動しない
		dp[ i + r ] = ( dp[ i + r ] + dp[ i ] ) % M;		// 起動する
	}
	return dp[ $ - 1 ];
}

// セグメント木
struct SegmentTree( alias op = ( ( a, b ) => a + b ), long I = long.init )
{
	long   n;
	long   nc;
	long   bc;
	long[] ps;
	
	this( long n )
	{
		this.n = n;
		for( nc = 1; nc < n; nc <<= 1 ){ /* nop */ }
		bc = nc - 1;
		ps.length = nc + bc;
		static if( I != long.init ) ps[] = I;
	}
	
	this( long[] qs )
	{
		this( qs.length );
		ps[ bc .. bc + qs.length ] = qs;
		foreach_reverse( i, ref p; ps[ 0L .. bc ] ) p = op( ps[ i * 2 + 1 ], ps[ i * 2 + 2 ] );
	}
	
	void set( long i, long v )
	{
		i = bc + i;
		ps[ i ] = v;
		while( 0 < i )
		{
			i = ( i - 1 ) / 2;
			ps[ i ] = op( ps[ i * 2 + 1 ], ps[ i * 2 + 2 ] );
		}
	}
	
	auto get( long i )
	{
		return ps[ bc + i ];
	}
	
	auto query( long l, long r )
	{
		long f( long l, long r, long i, long il, long ir )
		{
			if( ir <= l || r <= il ) return I;
			if( l <= il && ir <= r ) return ps[ i ];
			auto im = ( il + ir ) / 2;
			return op( f( l, r, i * 2 + 1, il, im ), f( l, r, i * 2 + 2, im, ir ) );
		}
		return f( l, r, 0, 0, nc );
	}
	
	auto length()
	{
		return n;
	}
	
	auto toString()
	{
		return ps[ bc .. bc + n ].to!( string );
	}
}
