#include <vector>
#include <functional>

template<class T, class F>
struct dual_segment_tree {
	using value_type = T;
	using size_type = std::size_t;
private : 
	size_type n;
	const F op;
	const value_type identity;
	std::vector<value_type> node;

	void propagate (size_type i) noexcept {
		if (node[i] == identity) return;
		node[i << 1 | 0] = op(node[i << 1 | 0], node[i]);
		node[i << 1 | 1] = op(node[i << 1 | 1], node[i]);
		node[i] = identity;
	}

	void topdown_update (size_type i) noexcept {
		if (i == 0) return;
		const size_type ctz = __builtin_ctz(i);
		for (size_type h = 31 - __builtin_clz(i); h != ctz; h--) {
			propagate(i >> h);
		}
	}

public : 
	explicit constexpr dual_segment_tree (const value_type &identity, const F &op) noexcept : identity(identity), op(op) { }

	void assign (size_type _size) noexcept {
		n = _size;
		node.assign(n << 1, identity);
	}

	void assign (size_type _size, const value_type &value) noexcept {
		assign(_size);
		for (size_type i = n; i < (n << 1); i++) {
			node[i] = value;
		}
	}

	template<class InputIterator>
	void assign (InputIterator first, InputIterator last) noexcept {
		assign(last - first);
		for (size_type i = n; first != last; i++, first++) {
			node[i] = (*first);
		}
	}

	void update (size_type first, size_type last, const value_type &value) noexcept {
		topdown_update(first + n); topdown_update(last + n);
		for (first += n, last += n; first != last; first >>= 1, last >>= 1) {
			if (first & 1) { node[first] = op(node[first], value); first++; }
			if (last & 1) { last--; node[last] = op(node[last], value); }
		}
	}

	value_type fold (size_type i) noexcept {
		value_type value = node[(i += n)];
		for (i >>= 1; i > 0; i >>= 1) {
			value = op(value, node[i]);
		}
		return value;
	}

	value_type operator[] (size_type i) noexcept {
		return fold(i);
	}

	value_type at (size_type i) noexcept {
		return fold(i);
	}

};

template<class Tp, class F>
dual_segment_tree<Tp, F> make_dualsegtree (const Tp &identity, const F &op) {
	return dual_segment_tree<Tp, F>(identity, op);
}

template<class InputIterator, class T, class F>
dual_segment_tree<T, F> make_dualsegtree (InputIterator first, InputIterator last, const T &identity, const F &op) {
	dual_segment_tree<T, F> segtree(identity, op);
	segtree.assign(first, last);
	return segtree;
}


#include <iostream>
#include <cstdint>
#include <cassert>

template<std::int_fast32_t Modulus>
struct modint {
	using value_type = std::int_fast32_t;

	static constexpr std::int_fast32_t mod = Modulus;
	static_assert(mod > 1, "Modulus must be greater than 1");

private :
	value_type x;

	template<class Tp>
	static constexpr value_type normalize (Tp value) noexcept {
		if (value < 0) {
			value = (-value) % mod;
			return (value ? value : mod - value);
		}
		return (value % mod);
	}

public :
	explicit constexpr modint () noexcept : x(0) { }

	template<class Tp>
	constexpr modint (Tp value) noexcept : x(normalize(value)) { }

	constexpr modint operator+ () const noexcept {
		return modint(*this);
	}

	constexpr modint operator- () noexcept {
		if (x != 0) x = mod - x;
		return modint(*this);
	}

	constexpr modint &operator+= (const modint &p) noexcept {
		if ((x += p.x) >= mod) x -= mod;
		return (*this);
	}

	constexpr modint &operator-= (const modint &p) noexcept {
		if ((x += mod - p.x) >= mod) x -= mod;
		return (*this);
	}

	constexpr modint &operator*= (const modint &p) noexcept {
		x = (int)(1LL * x * p.x % mod);
		return (*this);
	}

	constexpr modint &operator/= (const modint &p) noexcept {
		return ((*this) *= p.inverse());
	}

	constexpr modint operator+ (const modint &p) const noexcept {
		return (modint(*this) += p);
	}

	constexpr modint operator- (const modint &p) const noexcept {
		return (modint(*this) -= p);
	}

	constexpr modint operator* (const modint &p) const noexcept {
		return (modint(*this) *= p);
	}

	constexpr modint operator/ (const modint &p) const noexcept {
		return (modint(*this) /= p);
	}

	constexpr bool operator== (const modint &p) const noexcept {
		return (x == p.x);
	}

	constexpr bool operator!= (const modint &p) const noexcept {
		return (x != p.x);
	}

	template<class Tp>
	constexpr modint pow (Tp exp) const noexcept {
		modint value(1), buff(x);
		while (exp) {
			if (exp & 1) value *= buff;
			buff *= buff;
			exp >>= 1;
		}
		return value;
	}

	constexpr modint inverse () const noexcept {
		return pow(mod - 2);
	}

	friend std::ostream &operator<< (std::ostream &os, const modint &p) {
		return (os << p.x);
	}

	friend std::istream &operator>> (std::istream &is, modint &p) {
		long long v;
		is >> v;
		p = modint(v);
		return (is);
	}

};


#include <iostream>
#include <vector>
#include <cstddef>

using usize = std::size_t;

constexpr std::int_fast32_t MOD = 998244353;
constexpr usize MAX = 500000;

int main() {
	usize n, k;
	std::cin >> n >> k;
	std::vector<usize> l(k), r(k);
	for (usize i = 0; i < k; i++) {
		std::cin >> l[i] >> r[i];
	}
	
	auto f = [](const modint<MOD> &a, const modint<MOD> &b) {
		return a + b;
	};
	auto seg = make_dualsegtree(modint<MOD>(0), f);
	seg.assign(MAX, 0);
	seg.update(0, 1, 1);
	
	for (usize i = 0; i < n; i++) {
		for (usize j = 0; j < k; j++) {
			seg.update(i + l[j], i + r[j] + 1, seg[i]);
		}
	}
	
	std::cout << seg[n - 1] << '\n';
	
	return 0;
}

Measured memory_bytes: 11180