#include <bits/stdc++.h>
using namespace std;
struct aaa {
  aaa() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  };
} aaa;
template <class T>
ostream& operator<<(ostream& o, const vector<T>& v) {
  o << "{";
  for (int i = 0; i < (int)v.size(); i++) o << (i > 0 ? ", " : "") << v[i];
  o << "}";
  return o;
}
using int64 = long long;
const int MOD = 998244353;
class mint {
  using int64 = long long;

 private:
  int64 x;

 public:
  mint(const int64 x1 = 0) { x = x1 % MOD; };
  mint& operator++(int n) {
    x += 1;
    return *this;
  };
  mint& operator--(int n) {
    x -= 1;
    return *this;
  };
  mint& operator=(int64 n) {
    x = n % MOD;
    return *this;
  };
  mint& operator--() {
    x -= 1;
    return *this;
  };
  mint& operator+=(const mint a) {
    if ((x += a.x) >= MOD) x -= MOD;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += MOD - a.x) >= MOD) x -= MOD;
    return *this;
  }
  mint& operator*=(const mint a) {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint& operator/=(const mint a) { return (*this) *= a.inv(); }
  mint operator+(const mint a) const {
    mint res(*this);
    return res += a;
  }
  mint operator-(const mint a) const {
    mint res(*this);
    return res -= a;
  }
  mint operator*(const mint a) const {
    mint res(*this);
    return res *= a;
  }
  mint operator/(const mint a) const {
    mint res(*this);
    return res /= a;
  }
  mint inv() const { return pow(MOD - 2); }
  friend ostream& operator<<(ostream& os, const mint a) noexcept {
    return os << a.x;
  }
  constexpr bool operator==(const mint& r) const noexcept {
    return this->x == r.x;
  }
  constexpr bool operator!=(const mint& r) const noexcept {
    return this->x != r.x;
  }
  mint pow(long long t) const {
    if (!t) return mint(1);
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1) a *= *this;
    return a;
  }
};
template <typename Monoid, typename OperatorMonoid = Monoid>
struct LazySegmentTree {
  using F = function<Monoid(Monoid, Monoid)>;
  using G = function<Monoid(Monoid, OperatorMonoid)>;
  using H = function<OperatorMonoid(OperatorMonoid, OperatorMonoid)>;
  int sz, height;
  vector<Monoid> data;
  vector<OperatorMonoid> lazy;
  const F f;
  const G g;
  const H h;
  const Monoid M1;
  const OperatorMonoid OM0;
  LazySegmentTree(int n, const F f, const G g, const H h, const Monoid& M1,
                  const OperatorMonoid OM0)
      : f(f), g(g), h(h), M1(M1), OM0(OM0) {
    sz = 1;
    height = 0;
    while (sz < n) sz <<= 1, height++;
    data.assign(2 * sz, M1);
    lazy.assign(2 * sz, OM0);
  }
  void set(int k, const Monoid& x) { data[k + sz] = x; }
  void build() {
    for (int k = sz - 1; k > 0; k--) {
      data[k] = f(data[2 * k + 0], data[2 * k + 1]);
    }
  }
  inline void propagate(int k) {
    if (lazy[k] != OM0) {
      lazy[2 * k + 0] = h(lazy[2 * k + 0], lazy[k]);
      lazy[2 * k + 1] = h(lazy[2 * k + 1], lazy[k]);
      data[k] = reflect(k);
      lazy[k] = OM0;
    }
  }
  inline Monoid reflect(int k) {
    return lazy[k] == OM0 ? data[k] : g(data[k], lazy[k]);
  }
  inline void recalc(int k) {
    while (k >>= 1) data[k] = f(reflect(2 * k + 0), reflect(2 * k + 1));
  }
  inline void thrust(int k) {
    for (int i = height; i > 0; i--) propagate(k >> i);
  }
  void update(int a, int b, const OperatorMonoid& x) {
    thrust(a += sz);
    thrust(b += sz - 1);
    for (int l = a, r = b + 1; l < r; l >>= 1, r >>= 1) {
      if (l & 1) lazy[l] = h(lazy[l], x), ++l;
      if (r & 1) --r, lazy[r] = h(lazy[r], x);
    }
    recalc(a);
    recalc(b);
  }
  Monoid query(int a, int b) {
    thrust(a += sz);
    thrust(b += sz - 1);
    Monoid L = M1, R = M1;
    for (int l = a, r = b + 1; l < r; l >>= 1, r >>= 1) {
      if (l & 1) L = f(L, reflect(l++));
      if (r & 1) R = f(reflect(--r), R);
    }
    return f(L, R);
  }
  Monoid operator[](const int& k) { return query(k, k + 1); }
  template <typename C>
  int find_subtree(int a, const C& check, Monoid& M, bool type) {
    while (a < sz) {
      propagate(a);
      Monoid nxt =
          type ? f(reflect(2 * a + type), M) : f(M, reflect(2 * a + type));
      if (check(nxt))
        a = 2 * a + type;
      else
        M = nxt, a = 2 * a + 1 - type;
    }
    return a - sz;
  }
  template <typename C>
  int find_first(int a, const C& check) {
    Monoid L = M1;
    if (a <= 0) {
      if (check(f(L, reflect(1)))) return find_subtree(1, check, L, false);
      return -1;
    }
    thrust(a + sz);
    int b = sz;
    for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if (a & 1) {
        Monoid nxt = f(L, reflect(a));
        if (check(nxt)) return find_subtree(a, check, L, false);
        L = nxt;
        ++a;
      }
    }
    return -1;
  }
  template <typename C>
  int find_last(int b, const C& check) {
    Monoid R = M1;
    if (b >= sz) {
      if (check(f(reflect(1), R))) return find_subtree(1, check, R, true);
      return -1;
    }
    thrust(b + sz - 1);
    int a = sz;
    for (b += sz; a < b; a >>= 1, b >>= 1) {
      if (b & 1) {
        Monoid nxt = f(reflect(--b), R);
        if (check(nxt)) return find_subtree(b, check, R, true);
        R = nxt;
      }
    }
    return -1;
  }
};
int main() {
  int n, k;
  cin >> n >> k;
  const auto add = [](mint a, mint b) { return a + b; };
  LazySegmentTree<mint> seg(n, add, add, add, 0, 0);
  seg.set(0, 1);
  vector<pair<int, int>> lr;
  for (int i = 0; i < k; i++) {
    int l, r;
    cin >> l >> r;
    lr.emplace_back(l, r);
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < k; j++) {
      auto [l, r] = lr[j];
      if (i + l > n) continue;
      seg.update(i + l, min(n + 1, i + r + 1), seg.query(i, i + 1));
    }
  }
  cout << seg.query(n - 1, n) << endl;
}
