#include <bits/stdc++.h>

using namespace std;
using ll = long long;

const ll md = 998244353;

template <typename T>
class LazySegmentTree {
  vector<T> data_;
  vector<T> lazy_;
  int size_;

  void Eval(int k) {
    if (lazy_[k] == 0) {
      return;
    }

    if (k < size_ - 1) {
      lazy_[k * 2 + 1] += lazy_[k];
      lazy_[k * 2 + 2] += lazy_[k];
    }

    data_[k] += lazy_[k];
    lazy_[k] = 0;
  }

  void UpdateSub(int a, int b, T x, int k, int l, int r) {
    Eval(k);
    if (a <= l && r <= b) {
      lazy_[k] += x;
      Eval(k);
    } else if (a < r && l < b) {
      UpdateSub(a, b, x, k * 2 + 1, l, (l + r) / 2);
      UpdateSub(a, b, x, k * 2 + 2, (l + r) / 2, r);
      data_[k] = data_[k * 2 + 1] + data_[k * 2 + 2];
    }
  }

  T QuerySub(int a, int b, int k, int l, int r) {
    Eval(k);
    if (r <= a || b <= l) {
      return 0;
    } else if (a <= l && r <= b) {
      return data_[k];
    } else {
      return QuerySub(a, b, k * 2 + 1, l, (l + r) / 2) +
             QuerySub(a, b, k * 2 + 2, (l + r) / 2, r);
    }
  }

 public:
  LazySegmentTree(int size) : data_(), lazy_() {
    int n = 1;
    while (size > n) {
      n *= 2;
    }

    size_ = n;
    data_.resize(n * 2 - 1);
    lazy_.resize(n * 2 - 1);
    fill(data_.begin(), data_.end(), 0);
    fill(lazy_.begin(), lazy_.end(), 0);
  }

  void Update(int a, int b, T x) { UpdateSub(a, b, x, 0, 0, size_); }
  T Query(int a, int b) { return QuerySub(a, b, 0, 0, size_); }
  T Query(int a) { return Query(a, a + 1); }
};

namespace mod {

template <class T, int M>
class MInt;

template <class T, int M>
MInt<T, M> Pow(const MInt<T, M> &base, T exp);

template <class T, int M>
MInt<T, M> Inv(const MInt<T, M> &n);

template <class T, int M>
class MInt {
  T n_;

 public:
  MInt() : n_(0) {}
  MInt(T n) : n_((n % M + M) % M) {}

  MInt &operator+=(const MInt &rhs) {
    n_ += rhs.n_;
    if (n_ >= M) {
      n_ -= M;
    }

    return *this;
  }

  MInt &operator-=(const MInt &rhs) {
    n_ += M - rhs.n_;
    if (n_ >= M) {
      n_ -= M;
    }

    return *this;
  }

  MInt &operator*=(const MInt &rhs) {
    n_ = n_ * rhs.n_ % M;
    return *this;
  }

  MInt &operator/=(const MInt &rhs) { return (*this) *= Inv(rhs); }

  T Get() { return n_; }
};

template <class T, int M>
MInt<T, M> operator-(const MInt<T, M> &lhs, const MInt<T, M> &rhs) {
  MInt<T, M> res(lhs);
  return res -= rhs;
}

template <class T, int M>
MInt<T, M> operator+(const MInt<T, M> &lhs, const MInt<T, M> &rhs) {
  MInt<T, M> res(lhs);
  return res += rhs;
}

template <class T, int M>
MInt<T, M> operator*(const MInt<T, M> &lhs, const MInt<T, M> &rhs) {
  MInt<T, M> res(lhs);
  return res *= rhs;
}

template <class T, int M>
MInt<T, M> operator/(const MInt<T, M> &lhs, const MInt<T, M> &rhs) {
  MInt<T, M> res(lhs);
  return res /= rhs;
}

template <class T, int M>
MInt<T, M> Pow(const MInt<T, M> &base, T exp) {
  if (exp == 0) {
    return 1;
  }

  auto a = Pow(base, exp / 2);
  a *= a;
  if (exp % 2 == 1) {
    a *= base;
  }

  return a;
}

template <class T, int M>
MInt<T, M> Inv(const MInt<T, M> &n) {
  return Pow(n, static_cast<T>(M - 2));
}
}  // namespace mod

using MInt = mod::MInt<long long, md>;

int main(int argc, const char *argv[]) {
  int n, k;
  cin >> n >> k;

  vector<pair<int, int>> vp(k);
  for (auto &p : vp) {
    cin >> p.first >> p.second;
  }

  LazySegmentTree<MInt> seg_tree(n * 2 + 1);
  seg_tree.Update(0, 1, 1);
  for (int i = 0; i < n; ++i) {
    auto x = seg_tree.Query(i);
    for (auto &p : vp) {
      seg_tree.Update(i + p.first, p.second + 1, x);
    }
  }

  cout << seg_tree.Query(n).Get() << '\n';
  return 0;
}