// #include "atcoder/all"
#include <algorithm>
#include <bitset>
#include <cmath>
#include <complex>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <regex>
#include <set>
#include <stack>
#include <string>
#include <vector>

const int MOD = 998244353;
const int iINF = 2147483647 / 2;
const long long int llINF = 9223372036854775807 / 2;

using namespace std;
// using namespace atcoder;
using ll = long long int;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
using vvvl = vector<vector<vector<ll>>>;

typedef pair<ll, ll> pll;
bool paircomp(const pll &a, const pll &b) {
  if (a.first == b.first)
    return a.second < b.second;
  return a.first < b.first;
}

#define REP(i, n) for (ll i = 0; i < (n); i++)
#define RREP(i, n) for (ll i = (n)-1; i >= 0; i--)
#define FOR(i, a, b) for (ll i = (a); i < (b); i++)
#define AUTO(i, m) for (auto &i : m)
#define ALL(a) (a).begin(), (a).end()
#define MAX(vec) *std::max_element(vec.begin(), vec.end())
#define MIN(vec) *std::min_element(vec.begin(), vec.end())
#define ARGMAX(vec)                                                            \\
  std::distance(vec.begin(), std::max_element(vec.begin(), vec.end()))
#define ARGMIN(vec)                                                            \\
  std::distance(vec.begin(), std::min_element(vec.begin(), vec.end()))
#define REV(T) greater<T>()
#define PQ(T) priority_queue<T, vector<T>, greater<T>>
#define VVL(a, b, c) vector<vector<ll>>(a, vector<ll>(b, c))
#define VV(T, a, b, c) vector<vector<T>>(a, vector<T>(b, c))
#define VVVL(a, b, c, d)                                                       \\
  vector<vector<vector<ll>>>(a, vector<vector<ll>>(b, vector<ll>(c, d)))
#define VVV(T, a, b, c, d)                                                     \\
  vector<vector<vector<T>>>(a, vector<vector<T>>(b, vector<T>(c, d)))
#define SP(a) fixed << setprecision(a)
#define SQRT(a) sqrt((long double)(a))
#define DPOW(a, b) pow((long double)(a), (long double)(b))
#define UNIQUE(vec)                                                            \\
  do {                                                                         \\
    sort(ALL((vec)));                                                          \\
    (vec).erase(std::unique(ALL((vec))), (vec).end());                         \\
  } while (0)

ll MODPOW(ll n, ll m) {
  if (m == 0) {
    return 1;
  } else if (m % 2 == 0) {
    ll tmp = MODPOW(n, m / 2);
    return (tmp * tmp) % MOD;
  } else {
    return (n * MODPOW(n, m - 1)) % MOD;
  }
}

ll POW(ll n, ll m) {
  if (m == 0) {
    return 1;
  } else if (m % 2 == 0) {
    ll tmp = POW(n, m / 2);
    return (tmp * tmp);
  } else {
    return (n * POW(n, m - 1));
  }
}

int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  ll N, K;
  cin >> N >> K;
  vl L(K), R(K);
  set<ll> S;
  REP(i, K) {
    cin >> L[i] >> R[i];
    FOR(j, L[i], R[i] + 1) { S.insert(j); }
  }
  vl DP(2e5 + 10, 0);
  DP[1] = 1;
  FOR(i, 1, N) {
    AUTO(s, S) {
      if (i + s <= N) {
        DP[i + s] += DP[i];
        DP[i + s] %= MOD;
      }
    }
  }

  cout << DP[N] << endl;

  return 0;
}

// #include "atcoder/all"
#include <algorithm>
#include <bitset>
#include <cmath>
#include <complex>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <regex>
#include <set>
#include <stack>
#include <string>
#include <vector>

const int MOD = 998244353;
const int iINF = 2147483647 / 2;
const long long int llINF = 9223372036854775807 / 2;

using namespace std;
// using namespace atcoder;
using ll = long long int;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
using vvvl = vector<vector<vector<ll>>>;

typedef pair<ll, ll> pll;
bool paircomp(const pll &a, const pll &b) {
  if (a.first == b.first)
    return a.second < b.second;
  return a.first < b.first;
}

#define REP(i, n) for (ll i = 0; i < (n); i++)
#define RREP(i, n) for (ll i = (n)-1; i >= 0; i--)
#define FOR(i, a, b) for (ll i = (a); i < (b); i++)
#define AUTO(i, m) for (auto &i : m)
#define ALL(a) (a).begin(), (a).end()
#define MAX(vec) *std::max_element(vec.begin(), vec.end())
#define MIN(vec) *std::min_element(vec.begin(), vec.end())
#define ARGMAX(vec)                                                            \\
  std::distance(vec.begin(), std::max_element(vec.begin(), vec.end()))
#define ARGMIN(vec)                                                            \\
  std::distance(vec.begin(), std::min_element(vec.begin(), vec.end()))
#define REV(T) greater<T>()
#define PQ(T) priority_queue<T, vector<T>, greater<T>>
#define VVL(a, b, c) vector<vector<ll>>(a, vector<ll>(b, c))
#define VV(T, a, b, c) vector<vector<T>>(a, vector<T>(b, c))
#define VVVL(a, b, c, d)                                                       \\
  vector<vector<vector<ll>>>(a, vector<vector<ll>>(b, vector<ll>(c, d)))
#define VVV(T, a, b, c, d)                                                     \\
  vector<vector<vector<T>>>(a, vector<vector<T>>(b, vector<T>(c, d)))
#define SP(a) fixed << setprecision(a)
#define SQRT(a) sqrt((long double)(a))
#define DPOW(a, b) pow((long double)(a), (long double)(b))
#define UNIQUE(vec)                                                            \\
  do {                                                                         \\
    sort(ALL((vec)));                                                          \\
    (vec).erase(std::unique(ALL((vec))), (vec).end());                         \\
  } while (0)

ll MODPOW(ll n, ll m) {
  if (m == 0) {
    return 1;
  } else if (m % 2 == 0) {
    ll tmp = MODPOW(n, m / 2);
    return (tmp * tmp) % MOD;
  } else {
    return (n * MODPOW(n, m - 1)) % MOD;
  }
}

ll POW(ll n, ll m) {
  if (m == 0) {
    return 1;
  } else if (m % 2 == 0) {
    ll tmp = POW(n, m / 2);
    return (tmp * tmp);
  } else {
    return (n * POW(n, m - 1));
  }
}

int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  ll N, K;
  cin >> N >> K;
  vl L(K), R(K);
  set<ll> S;

  REP(i, K) {
    cin >> L[i] >> R[i];
    FOR(j, L[i], R[i] + 1) { S.insert(j); }
  }
  vl DP(N);
  DP[0] = 1;
  DP[1] = -1;
  REP(i, N) {
    if (i > 0) {
      DP[i] += DP[i - 1];
      DP[i] %= MOD;
    }
    REP(k, K) {
      ll l = L[k];
      ll r = R[k] + 1;
      if (i + l < N) {
        DP[i + l] += DP[i];
        DP[i + l] %= MOD;
      }
      if (i + r < N) {
        DP[i + r] -= DP[i] - MOD;
        DP[i + r] %= MOD;
      }
    }
  }

  cout << DP[N - 1] << endl;

  return 0;
}


#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>

using namespace std;
#define ll long long
#define ull unsigned long long
#define rep(i, m, n) for (ll(i) = (ll)(m); i < (ll)(n); i++)
#define REP(i, n) rep(i, 0, n)
#define all(hoge) (hoge).begin(), (hoge).end()
typedef pair<ll, ll> P;
constexpr long double m_pi = 3.1415926535897932L;
constexpr ll MOD = 1000000007;
constexpr ll INF = 1LL << 61;
constexpr long double EPS = 1e-10;
template <typename T> using vector2 = vector<vector<T>>;
template <typename T> using vector3 = vector<vector2<T>>;
typedef vector<ll> Array;
typedef vector<Array> Matrix;
string operator*(const string &s, int k) {
  if (k == 0)
    return "";
  string p = (s + s) * (k / 2);
  if (k % 2 == 1)
    p += s;
  return p;
}

template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

struct Edge { // グラフ
  int to, rev;
  ll cap;
  Edge(int _to, ll _cap, int _rev) {
    to = _to;
    cap = _cap;
    rev = _rev;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
void add_edge(Graph &G, int from, int to, ll cap, bool revFlag,
              ll revCap) { // 最大フロー求める Ford-fulkerson
  G[from].push_back(Edge(to, cap, (ll)G[to].size() + (from == to)));
  if (revFlag)
    G[to].push_back(Edge(
        from, revCap, (ll)G[from].size() - 1)); // 最小カットの場合逆辺は0にする
}

ll max_flow_dfs(Graph &G, ll v, ll t, ll f, vector<bool> &used) {
  if (v == t)
    return f;
  used[v] = true;
  for (int i = 0; i < G[v].size(); ++i) {
    Edge &e = G[v][i];
    if (!used[e.to] && e.cap > 0) {
      ll d = max_flow_dfs(G, e.to, t, min(f, e.cap), used);
      if (d > 0) {
        e.cap -= d;
        G[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0;
}
// 二分グラフの最大マッチングを求めたりも出来る　また二部グラフの最大独立集合は頂点数-最大マッチングのサイズ
ll max_flow(Graph &G, ll s, ll t) // O(V(V+E))
{
  ll flow = 0;
  for (;;) {
    vector<bool> used(G.size());
    REP(i, used.size()) used[i] = false;
    ll f = max_flow_dfs(G, s, t, INF, used);
    if (f == 0) {
      return flow;
    }
    flow += f;
  }
}

void BellmanFord(Graph &G, ll s, Array &d, Array &negative) { // O(|E||V|)
  d.resize(G.size());
  negative.resize(G.size());
  REP(i, d.size()) d[i] = INF;
  REP(i, d.size()) negative[i] = false;
  d[s] = 0;
  REP(k, G.size() - 1) {
    REP(i, G.size()) {
      REP(j, G[i].size()) {
        if (d[i] != INF && d[G[i][j].to] > d[i] + G[i][j].cap) {
          d[G[i][j].to] = d[i] + G[i][j].cap;
        }
      }
    }
  }
  REP(k, G.size() - 1) {
    REP(i, G.size()) {
      REP(j, G[i].size()) {
        if (d[i] != INF && d[G[i][j].to] > d[i] + G[i][j].cap) {
          d[G[i][j].to] = d[i] + G[i][j].cap;
          negative[G[i][j].to] = true;
        }
        if (negative[i] == true)
          negative[G[i][j].to] = true;
      }
    }
  }
}
void Dijkstra(Graph &G, ll s, Array &d) { // O(|E|log|V|)
  d.resize(G.size());
  REP(i, d.size()) d[i] = INF;
  d[s] = 0;
  priority_queue<P, vector<P>, greater<P>> q;
  q.push(make_pair(0, s));
  while (!q.empty()) {
    P a = q.top();
    q.pop();
    if (d[a.second] < a.first)
      continue;
    REP(i, G[a.second].size()) {
      Edge e = G[a.second][i];
      if (d[e.to] > d[a.second] + e.cap) {
        d[e.to] = d[a.second] + e.cap;
        q.push(make_pair(d[e.to], e.to));
      }
    }
  }
}
void WarshallFloyd(Graph &G, Matrix &d) { // O(V^3)
  d.resize(G.size());
  REP(i, d.size()) d[i].resize(G.size());
  REP(i, d.size()) {
    REP(j, d[i].size()) { d[i][j] = ((i != j) ? INF : 0); }
  }
  REP(i, G.size()) {
    REP(j, G[i].size()) { chmin(d[i][G[i][j].to], G[i][j].cap); }
  }
  REP(i, G.size()) {
    REP(j, G.size()) {
      REP(k, G.size()) {
        if (d[j][i] != INF && d[i][k] != INF)
          chmin(d[j][k], d[j][i] + d[i][k]);
      }
    }
  }
}
bool tsort(Graph &graph, vector<int> &order) { // トポロジカルソートO(E+V)
  int n = graph.size(), k = 0;
  vector<int> in(n);
  for (auto &es : graph)
    for (auto &e : es)
      in[e.to]++;
  priority_queue<int, vector<int>, greater<int>> que;
  REP(i, n)
  if (in[i] == 0)
    que.push(i);
  while (que.size()) {
    int v = que.top();
    que.pop();
    order.push_back(v);
    for (auto &e : graph[v])
      if (--in[e.to] == 0)
        que.push(e.to);
  }
  if (order.size() != n)
    return false;
  else
    return true;
}
class Lca {
public:
  const int n = 0;
  const int log2_n = 0;
  std::vector<std::vector<int>> parent;
  std::vector<int> depth;

  Lca() {}

  Lca(const Graph &g, int root)
      : n(g.size()), log2_n(log2(n) + 1), parent(log2_n, std::vector<int>(n)),
        depth(n) {
    dfs(g, root, -1, 0);
    for (int k = 0; k + 1 < log2_n; k++) {
      for (int v = 0; v < (int)g.size(); v++) {
        if (parent[k][v] < 0)
          parent[k + 1][v] = -1;
        else
          parent[k + 1][v] = parent[k][parent[k][v]];
      }
    }
  }

  void dfs(const Graph &g, int v, int p, int d) {
    parent[0][v] = p;
    depth[v] = d;
    for (auto &e : g[v]) {
      if (e.to != p)
        dfs(g, e.to, v, d + 1);
    }
  }

  int get(int u, int v) {
    if (depth[u] > depth[v])
      std::swap(u, v);
    for (int k = 0; k < log2_n; k++) {
      if ((depth[v] - depth[u]) >> k & 1) {
        v = parent[k][v];
      }
    }
    if (u == v)
      return u;
    for (int k = log2_n - 1; k >= 0; k--) {
      if (parent[k][u] != parent[k][v]) {
        u = parent[k][u];
        v = parent[k][v];
      }
    }
    return parent[0][u];
  }
};

class UnionFind {
  vector<int> data;
  int n;

public:
  UnionFind(int size) : data(size, -1), n(size) {}
  bool merge(int x, int y) { // xとyの集合を統合する
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x])
        swap(x, y);
      data[x] += data[y];
      data[y] = x;
    }
    n -= (x != y);
    return x != y;
  }
  bool same(int x, int y) { // xとyが同じ集合か返す
    return root(x) == root(y);
  }
  int root(int x) { // xのルートを返す
    return data[x] < 0 ? x : data[x] = root(data[x]);
  }
  int size(int x) { // xの集合のサイズを返す
    return -data[root(x)];
  }
  int num() { // 集合の数を返す
    return n;
  }
};

template <typename T, typename F> class SegmentTree {
private:
  T identity;
  F merge;
  ll n;
  vector<T> dat;

public:
  SegmentTree(F f, T id, vector<T> v) : merge(f), identity(id) {
    int _n = v.size();
    n = 1;
    while (n < _n)
      n *= 2;
    dat.resize(2 * n - 1, identity);
    REP(i, _n) dat[n + i - 1] = v[i];
    for (int i = n - 2; i >= 0; i--)
      dat[i] = merge(dat[i * 2 + 1], dat[i * 2 + 2]);
  }
  SegmentTree(F f, T id, int _n) : merge(f), identity(id) {
    n = 1;
    while (n < _n)
      n *= 2;
    dat.resize(2 * n - 1, identity);
  }
  void set_val(int i, T x) {
    i += n - 1;
    dat[i] = x;
    while (i > 0) {
      i = (i - 1) / 2;
      dat[i] = merge(dat[i * 2 + 1], dat[i * 2 + 2]);
    }
  }
  T query(int l, int r) {
    T left = identity, right = identity;
    l += n - 1;
    r += n - 1;
    while (l < r) {
      if ((l & 1) == 0)
        left = merge(left, dat[l]);
      if ((r & 1) == 0)
        right = merge(dat[r - 1], right);
      l = l / 2;
      r = (r - 1) / 2;
    }
    return merge(left, right);
  }
};

template <typename T> class FenwickTree {
  vector<T> data;
  int n;
  int p;

public:
  FenwickTree(int n) : n(n) {
    data.resize(n + 1LL, 0);
    p = 1;
    while (p < data.size())
      p *= 2;
  }
  T sum(int k) {
    T ret = 0;
    for (; k > 0; k -= k & -k)
      ret += data[k];
    return (ret);
  }

  T sum(int a, int b) { return sum(b) - sum(a); } //[a,b)

  void add(int k, T x) {
    for (++k; k <= n; k += k & -k)
      data[k] += x;
  }

  int lower_bound(ll w) {
    if (w <= 0)
      return -1;
    int x = 0;
    for (int k = p / 2; k > 0; k /= 2) {
      if (x + k <= n && data[x + k] < w)
        w -= data[x + k], x += k;
    }
    return x;
  }
};

// 約数求める //約数
void divisor(ll n, vector<ll> &ret) {
  for (ll i = 1; i * i <= n; i++) {
    if (n % i == 0) {
      ret.push_back(i);
      if (i * i != n)
        ret.push_back(n / i);
    }
  }
  sort(ret.begin(), ret.end());
}

void prime_factorization(ll n, vector<P> &ret) {
  for (ll i = 2; i * i <= n; i++) {
    if (n % i == 0) {
      ret.push_back({i, 0});
      while (n % i == 0) {
        n /= i;
        ret[ret.size() - 1].second++;
      }
    }
  }
  if (n != 1)
    ret.push_back({n, 1});
}

inline ll mod_pow(ll x, ll n, ll mod) {
  ll res = 1;
  while (n > 0) {
    if (n & 1)
      res = res * x % mod;
    x = x * x % mod;
    n >>= 1;
  }
  return res;
}

inline ll mod_inv(ll x, ll mod) { return mod_pow(x, mod - 2, mod); }

class Combination {
public:
  Array fact;
  Array fact_inv;
  ll mod;
  // if n >= mod use lucas
  ll nCr(ll n, ll r) {
    if (n < r)
      return 0;
    if (n < mod)
      return ((fact[n] * fact_inv[r] % mod) * fact_inv[n - r]) % mod;

    ll ret = 1;
    while (n || r) {
      ll _n = n % mod, _r = r % mod;
      n /= mod;
      r /= mod;
      (ret *= nCr(_n, _r)) %= mod;
    }
    return ret;
  }
  ll nPr(ll n, ll r) { return (fact[n] * fact_inv[n - r]) % mod; }
  ll nHr(ll n, ll r) { return nCr(r + n - 1, r); }
  Combination(ll _n, ll _mod) {
    mod = _mod;
    ll n = min(_n + 1, mod);
    fact.resize(n);
    fact[0] = 1;
    REP(i, n - 1) { fact[i + 1] = (fact[i] * (i + 1LL)) % mod; }
    fact_inv.resize(n);
    fact_inv[n - 1] = mod_inv(fact[n - 1], mod);
    for (int i = n - 1; i > 0; i--) {
      fact_inv[i - 1] = fact_inv[i] * i % mod;
    }
  }
};

ll popcount(ll x) {
  x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555);
  x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333);
  x = (x & 0x0F0F0F0F0F0F0F0F) + (x >> 4 & 0x0F0F0F0F0F0F0F0F);
  x = (x & 0x00FF00FF00FF00FF) + (x >> 8 & 0x00FF00FF00FF00FF);
  x = (x & 0x0000FFFF0000FFFF) + (x >> 16 & 0x0000FFFF0000FFFF);
  x = (x & 0x00000000FFFFFFFF) + (x >> 32 & 0x00000000FFFFFFFF);

  return x;
}

ll dp[202020];

int main() {
  ios::sync_with_stdio(false);
  std::cin.tie(0);
  std::cout.tie(0);

  constexpr ll mod = 998244353;
  ll n, k;
  cin >> n >> k;
  Array l(k), r(k);
  REP(i, k) cin >> l[i] >> r[i];
  dp[1] = 1;
  rep(i, 1, n) {
    (dp[i] += dp[i - 1]) %= mod;
    REP(j, k) {
      (dp[i + l[j]] += dp[i]) %= mod;
      (dp[i + r[j] + 1] += mod - dp[i]) %= mod;
    }
  }
  cout << dp[n] << "\\n";

  return 0;
}

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>

using namespace std;
#define ll long long
#define ull unsigned long long
#define rep(i, m, n) for (ll(i) = (ll)(m); i < (ll)(n); i++)
#define REP(i, n) rep(i, 0, n)
#define all(hoge) (hoge).begin(), (hoge).end()
typedef pair<ll, ll> P;
constexpr long double m_pi = 3.1415926535897932L;
constexpr ll MOD = 1000000007;
constexpr ll INF = 1LL << 61;
constexpr long double EPS = 1e-10;
template <typename T> using vector2 = vector<vector<T>>;
template <typename T> using vector3 = vector<vector2<T>>;
typedef vector<ll> Array;
typedef vector<Array> Matrix;
string operator*(const string &s, int k) {
  if (k == 0)
    return "";
  string p = (s + s) * (k / 2);
  if (k % 2 == 1)
    p += s;
  return p;
}

template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

struct Edge { // グラフ
  int to, rev;
  ll cap;
  Edge(int _to, ll _cap, int _rev) {
    to = _to;
    cap = _cap;
    rev = _rev;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
void add_edge(Graph &G, int from, int to, ll cap, bool revFlag,
              ll revCap) { // 最大フロー求める Ford-fulkerson
  G[from].push_back(Edge(to, cap, (ll)G[to].size() + (from == to)));
  if (revFlag)
    G[to].push_back(Edge(
        from, revCap, (ll)G[from].size() - 1)); // 最小カットの場合逆辺は0にする
}

ll max_flow_dfs(Graph &G, ll v, ll t, ll f, vector<bool> &used) {
  if (v == t)
    return f;
  used[v] = true;
  for (int i = 0; i < G[v].size(); ++i) {
    Edge &e = G[v][i];
    if (!used[e.to] && e.cap > 0) {
      ll d = max_flow_dfs(G, e.to, t, min(f, e.cap), used);
      if (d > 0) {
        e.cap -= d;
        G[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0;
}
// 二分グラフの最大マッチングを求めたりも出来る　また二部グラフの最大独立集合は頂点数-最大マッチングのサイズ
ll max_flow(Graph &G, ll s, ll t) // O(V(V+E))
{
  ll flow = 0;
  for (;;) {
    vector<bool> used(G.size());
    REP(i, used.size()) used[i] = false;
    ll f = max_flow_dfs(G, s, t, INF, used);
    if (f == 0) {
      return flow;
    }
    flow += f;
  }
}

void BellmanFord(Graph &G, ll s, Array &d, Array &negative) { // O(|E||V|)
  d.resize(G.size());
  negative.resize(G.size());
  REP(i, d.size()) d[i] = INF;
  REP(i, d.size()) negative[i] = false;
  d[s] = 0;
  REP(k, G.size() - 1) {
    REP(i, G.size()) {
      REP(j, G[i].size()) {
        if (d[i] != INF && d[G[i][j].to] > d[i] + G[i][j].cap) {
          d[G[i][j].to] = d[i] + G[i][j].cap;
        }
      }
    }
  }
  REP(k, G.size() - 1) {
    REP(i, G.size()) {
      REP(j, G[i].size()) {
        if (d[i] != INF && d[G[i][j].to] > d[i] + G[i][j].cap) {
          d[G[i][j].to] = d[i] + G[i][j].cap;
          negative[G[i][j].to] = true;
        }
        if (negative[i] == true)
          negative[G[i][j].to] = true;
      }
    }
  }
}
void Dijkstra(Graph &G, ll s, Array &d) { // O(|E|log|V|)
  d.resize(G.size());
  REP(i, d.size()) d[i] = INF;
  d[s] = 0;
  priority_queue<P, vector<P>, greater<P>> q;
  q.push(make_pair(0, s));
  while (!q.empty()) {
    P a = q.top();
    q.pop();
    if (d[a.second] < a.first)
      continue;
    REP(i, G[a.second].size()) {
      Edge e = G[a.second][i];
      if (d[e.to] > d[a.second] + e.cap) {
        d[e.to] = d[a.second] + e.cap;
        q.push(make_pair(d[e.to], e.to));
      }
    }
  }
}
void WarshallFloyd(Graph &G, Matrix &d) { // O(V^3)
  d.resize(G.size());
  REP(i, d.size()) d[i].resize(G.size());
  REP(i, d.size()) {
    REP(j, d[i].size()) { d[i][j] = ((i != j) ? INF : 0); }
  }
  REP(i, G.size()) {
    REP(j, G[i].size()) { chmin(d[i][G[i][j].to], G[i][j].cap); }
  }
  REP(i, G.size()) {
    REP(j, G.size()) {
      REP(k, G.size()) {
        if (d[j][i] != INF && d[i][k] != INF)
          chmin(d[j][k], d[j][i] + d[i][k]);
      }
    }
  }
}
bool tsort(Graph &graph, vector<int> &order) { // トポロジカルソートO(E+V)
  int n = graph.size(), k = 0;
  vector<int> in(n);
  for (auto &es : graph)
    for (auto &e : es)
      in[e.to]++;
  priority_queue<int, vector<int>, greater<int>> que;
  REP(i, n)
  if (in[i] == 0)
    que.push(i);
  while (que.size()) {
    int v = que.top();
    que.pop();
    order.push_back(v);
    for (auto &e : graph[v])
      if (--in[e.to] == 0)
        que.push(e.to);
  }
  if (order.size() != n)
    return false;
  else
    return true;
}
class Lca {
public:
  const int n = 0;
  const int log2_n = 0;
  std::vector<std::vector<int>> parent;
  std::vector<int> depth;

  Lca() {}

  Lca(const Graph &g, int root)
      : n(g.size()), log2_n(log2(n) + 1), parent(log2_n, std::vector<int>(n)),
        depth(n) {
    dfs(g, root, -1, 0);
    for (int k = 0; k + 1 < log2_n; k++) {
      for (int v = 0; v < (int)g.size(); v++) {
        if (parent[k][v] < 0)
          parent[k + 1][v] = -1;
        else
          parent[k + 1][v] = parent[k][parent[k][v]];
      }
    }
  }

  void dfs(const Graph &g, int v, int p, int d) {
    parent[0][v] = p;
    depth[v] = d;
    for (auto &e : g[v]) {
      if (e.to != p)
        dfs(g, e.to, v, d + 1);
    }
  }

  int get(int u, int v) {
    if (depth[u] > depth[v])
      std::swap(u, v);
    for (int k = 0; k < log2_n; k++) {
      if ((depth[v] - depth[u]) >> k & 1) {
        v = parent[k][v];
      }
    }
    if (u == v)
      return u;
    for (int k = log2_n - 1; k >= 0; k--) {
      if (parent[k][u] != parent[k][v]) {
        u = parent[k][u];
        v = parent[k][v];
      }
    }
    return parent[0][u];
  }
};

class UnionFind {
  vector<int> data;
  int n;

public:
  UnionFind(int size) : data(size, -1), n(size) {}
  bool merge(int x, int y) { // xとyの集合を統合する
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x])
        swap(x, y);
      data[x] += data[y];
      data[y] = x;
    }
    n -= (x != y);
    return x != y;
  }
  bool same(int x, int y) { // xとyが同じ集合か返す
    return root(x) == root(y);
  }
  int root(int x) { // xのルートを返す
    return data[x] < 0 ? x : data[x] = root(data[x]);
  }
  int size(int x) { // xの集合のサイズを返す
    return -data[root(x)];
  }
  int num() { // 集合の数を返す
    return n;
  }
};

template <typename T, typename F> class SegmentTree {
private:
  T identity;
  F merge;
  ll n;
  vector<T> dat;

public:
  SegmentTree(F f, T id, vector<T> v) : merge(f), identity(id) {
    int _n = v.size();
    n = 1;
    while (n < _n)
      n *= 2;
    dat.resize(2 * n - 1, identity);
    REP(i, _n) dat[n + i - 1] = v[i];
    for (int i = n - 2; i >= 0; i--)
      dat[i] = merge(dat[i * 2 + 1], dat[i * 2 + 2]);
  }
  SegmentTree(F f, T id, int _n) : merge(f), identity(id) {
    n = 1;
    while (n < _n)
      n *= 2;
    dat.resize(2 * n - 1, identity);
  }
  void set_val(int i, T x) {
    i += n - 1;
    dat[i] = x;
    while (i > 0) {
      i = (i - 1) / 2;
      dat[i] = merge(dat[i * 2 + 1], dat[i * 2 + 2]);
    }
  }
  T query(int l, int r) {
    T left = identity, right = identity;
    l += n - 1;
    r += n - 1;
    while (l < r) {
      if ((l & 1) == 0)
        left = merge(left, dat[l]);
      if ((r & 1) == 0)
        right = merge(dat[r - 1], right);
      l = l / 2;
      r = (r - 1) / 2;
    }
    return merge(left, right);
  }
};

template <typename T> class FenwickTree {
  vector<T> data;
  int n;
  int p;

public:
  FenwickTree(int n) : n(n) {
    data.resize(n + 1LL, 0);
    p = 1;
    while (p < data.size())
      p *= 2;
  }
  T sum(int k) {
    T ret = 0;
    for (; k > 0; k -= k & -k)
      ret += data[k];
    return (ret);
  }

  T sum(int a, int b) { return sum(b) - sum(a); } //[a,b)

  void add(int k, T x) {
    for (++k; k <= n; k += k & -k)
      data[k] += x;
  }

  int lower_bound(ll w) {
    if (w <= 0)
      return -1;
    int x = 0;
    for (int k = p / 2; k > 0; k /= 2) {
      if (x + k <= n && data[x + k] < w)
        w -= data[x + k], x += k;
    }
    return x;
  }
};

// 約数求める //約数
void divisor(ll n, vector<ll> &ret) {
  for (ll i = 1; i * i <= n; i++) {
    if (n % i == 0) {
      ret.push_back(i);
      if (i * i != n)
        ret.push_back(n / i);
    }
  }
  sort(ret.begin(), ret.end());
}

void prime_factorization(ll n, vector<P> &ret) {
  for (ll i = 2; i * i <= n; i++) {
    if (n % i == 0) {
      ret.push_back({i, 0});
      while (n % i == 0) {
        n /= i;
        ret[ret.size() - 1].second++;
      }
    }
  }
  if (n != 1)
    ret.push_back({n, 1});
}

inline ll mod_pow(ll x, ll n, ll mod) {
  ll res = 1;
  while (n > 0) {
    if (n & 1)
      res = res * x % mod;
    x = x * x % mod;
    n >>= 1;
  }
  return res;
}

inline ll mod_inv(ll x, ll mod) { return mod_pow(x, mod - 2, mod); }

class Combination {
public:
  Array fact;
  Array fact_inv;
  ll mod;
  // if n >= mod use lucas
  ll nCr(ll n, ll r) {
    if (n < r)
      return 0;
    if (n < mod)
      return ((fact[n] * fact_inv[r] % mod) * fact_inv[n - r]) % mod;

    ll ret = 1;
    while (n || r) {
      ll _n = n % mod, _r = r % mod;
      n /= mod;
      r /= mod;
      (ret *= nCr(_n, _r)) %= mod;
    }
    return ret;
  }
  ll nPr(ll n, ll r) { return (fact[n] * fact_inv[n - r]) % mod; }
  ll nHr(ll n, ll r) { return nCr(r + n - 1, r); }
  Combination(ll _n, ll _mod) {
    mod = _mod;
    ll n = min(_n + 1, mod);
    fact.resize(n);
    fact[0] = 1;
    REP(i, n - 1) { fact[i + 1] = (fact[i] * (i + 1LL)) % mod; }
    fact_inv.resize(n);
    fact_inv[n - 1] = mod_inv(fact[n - 1], mod);
    for (int i = n - 1; i > 0; i--) {
      fact_inv[i - 1] = fact_inv[i] * i % mod;
    }
  }
};

ll popcount(ll x) {
  x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555);
  x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333);
  x = (x & 0x0F0F0F0F0F0F0F0F) + (x >> 4 & 0x0F0F0F0F0F0F0F0F);
  x = (x & 0x00FF00FF00FF00FF) + (x >> 8 & 0x00FF00FF00FF00FF);
  x = (x & 0x0000FFFF0000FFFF) + (x >> 16 & 0x0000FFFF0000FFFF);
  x = (x & 0x00000000FFFFFFFF) + (x >> 32 & 0x00000000FFFFFFFF);

  return x;
}

ll dp[502020];

int main() {
  ios::sync_with_stdio(false);
  std::cin.tie(0);
  std::cout.tie(0);

  constexpr ll mod = 998244353;
  ll n, k;
  cin >> n >> k;
  Array l(k), r(k);
  REP(i, k) cin >> l[i] >> r[i];
  dp[1] = 1;
  rep(i, 1, n) {
    (dp[i] += dp[i - 1]) %= mod;
    REP(j, k) {
      (dp[i + l[j]] += dp[i]) %= mod;
      (dp[i + r[j] + 1] += mod - dp[i]) %= mod;
    }
  }
  cout << dp[n] << "\\n";

  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
int p = 998244353;
int32_t main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  int t, n, i, j, k, l, r;
  cin >> n >> k;
  set<int> s;

  for (i = 1; i <= k; i++) {
    cin >> l >> r;
    for (j = l; j <= r; j++)
      s.insert(j);
  }
  int dp[n + 1];
  memset(dp, 0, sizeof(dp));
  dp[0] = 0;
  dp[1] = 1;
  for (i = 2; i <= n; i++) {
    for (auto it = s.begin(); it != s.end(); it++) {
      j = *it;
      if (j <= i)
        dp[i] = (dp[i] + dp[i - j]) % p;
      else
        break;
    }
  }
  cout << dp[n] % p;
}

#include <bits/stdc++.h>
using namespace std;
#define int long long
int p = 998244353;
int32_t main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  int t, n, i, j, k, l, r, l1;
  cin >> n >> k;
  vector<pair<int, int>> v;
  for (i = 1; i <= k; i++) {
    cin >> l >> r;
    v.push_back({l, r});
  }
  sort(v.begin(), v.end());
  int dp[n + 1];
  memset(dp, 0, sizeof(dp));
  dp[0] = 0;
  dp[1] = 1;
  int dp1[n + 1];
  dp[0] = 0;
  dp[1] = 1;
  dp1[0] = 0;
  dp1[1] = 1;
  for (i = 2; i <= n; i++) {
    for (j = 0; j < v.size(); j++) {
      l = v[j].first, k = v[j].second;
      k = min(k, i);
      if (l <= k) {
        if (i == k)
          l1 = ((dp1[i - l] - dp1[i - k]) % p + p) % p;
        else
          l1 = ((dp1[i - l] - dp1[i - k - 1]) % p + p) % p;
        dp[i] = (dp[i] + l1) % p;
      }
    }
    dp1[i] = (dp[i] + dp1[i - 1]) % p;
  }
  cout << dp[n] % p;
}


#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

vector<int> s;
vector<unsigned long long int> dp;
vector<int> tmp;

int main() {

  int n, k;
  cin >> n >> k;

  for (int i = 0; i < k; i++) {
    int t1, t2;
    cin >> t1 >> t2;
    tmp.push_back(t1);
    tmp.push_back(t2);
  }

  sort(tmp.begin(), tmp.end());

  for (int i = 0; i < 2 * k; i = i + 2)
    for (int j = tmp[i]; j <= tmp[i + 1]; j++)
      s.push_back(j);

  dp.resize(n, 0);

  dp[0] = 1;

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < s.size() && i + s[j] < n; j++) {
      dp[i + s[j]] += dp[i];
    }
  }

  cout << dp[n - 1] % 998244353 << endl;
}

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

vector<int> s;
vector<unsigned long long int> dp;
vector<unsigned long long int> dpsum;
vector<int> l;
vector<int> r;
vector<int> tmp;
long long mod = 998244353;

int main() {

  int n, k;
  cin >> n >> k;

  for (int i = 0; i < k; i++) {
    int t1, t2;
    cin >> t1 >> t2;
    l.push_back(t1);
    r.push_back(t2);
  }

  dp.resize(n + 1, 0);
  dpsum.resize(n + 1, 0);
  dp[1] = 1;
  dpsum[1] = 1;

  for (int i = 2; i <= n; i++) {
    for (int j = 0; j < k; j++) {
      int ll = i - r[j];
      ll = max(ll, 1);
      int rr = i - l[j];
      if (rr < 0)
        continue;
      dp[i] += dpsum[rr] - dpsum[ll - 1];
      dp[i] = (dp[i]) % mod;
    }
    dpsum[i] = dpsum[i - 1] + dp[i];
  }

  cout << dp[n] << endl;
}


#include <algorithm>
#include <cstdio>
#include <functional>
#include <iostream>
#include <map>
#include <set>
#include <string>
using namespace std;
using ll = long long;

#define rep(i, n) for (int i = 0; i < (n); i++)
#define rep1(i, n) for (int i = 1; i <= (n); i++)

int L[10];
int R[10];

bool Map[200007];
int K;
bool in(int x) {
  for (int i = 0; i < K; i++) {
    if (L[i] <= x && x <= R[i])
      return true;
  }
  return false;
}

int path(int from, int to) {
  int ans = 0;
  if (from > to)
    return 0;
  if (from == to)
    return 1;
  for (int i = 0; i < K; i++) {
    for (int j = L[i]; j <= R[i]; j++) {
      ans += path(from + j, to);
      ans %= 998244353;
    }
  }
  return ans;
}

int ans[200007];

int main() {

  cin.tie(0);
  ios::sync_with_stdio(false);
  int N;

  ans[1] = 1;
  cin >> N >> K;
  int count = 0;
  rep(i, K) {
    int l, r;
    cin >> l >> r;
    L[i] = l;
    R[i] = r;
    /*for (int j = l; j <= r; j++) {
        Map[j] = true;
    }*/
  }
  rep1(i, N) {
    rep(p, K) {
      for (int j = L[p]; j <= R[p]; j++) {
        if (j <= i)
          ans[i] += ans[i - j], ans[i] %= 998244353;
      }
    }
  }

  // rep1(i, N)cout << i << ": " << ans[i] << endl;
  cout << ans[N] << endl;
  return 0;
}

#include <algorithm>
#include <cstdio>
#include <functional>
#include <iostream>
#include <map>
#include <set>
#include <string>
using namespace std;
using ll = long long;

#define rep(i, n) for (int i = 0; i < (n); i++)
#define rep1(i, n) for (int i = 1; i <= (n); i++)

int L[10];
int R[10];

bool Map[200007];
int K;
bool in(int x) {
  for (int i = 0; i < K; i++) {
    if (L[i] <= x && x <= R[i])
      return true;
  }
  return false;
}

int path(int from, int to) {
  int ans = 0;
  if (from > to)
    return 0;
  if (from == to)
    return 1;
  for (int i = 0; i < K; i++) {
    for (int j = L[i]; j <= R[i]; j++) {
      ans += path(from + j, to);
      ans %= 998244353;
    }
  }
  return ans;
}

ll ans[200007];
ll anssum[200007];
int main() {

  cin.tie(0);
  ios::sync_with_stdio(false);
  int N;

  ans[1] = 1;
  anssum[1] = 1;
  cin >> N >> K;
  int count = 0;
  rep(i, K) {
    int l, r;
    cin >> l >> r;
    L[i] = l;
    R[i] = r;
    /*for (int j = l; j <= r; j++) {
        Map[j] = true;
    }*/
  }
  /*rep1(i, N) {
      rep(p, K) {
          for (int j = L[p]; j <= R[p]; j++) {
              if (j <= i)ans[i] += ans[i - j], ans[i] %= 998244353;
          }
          anssum[i] = anssum[i] + ans[i];
      }
  }*/

  for (int i = 2; i <= N; i++) {
    rep(p, K) {
      /*for (int j = L[p]; j <= R[p]; j++) {
          if (j <= i)ans[i] += ans[i - j], ans[i] %= 998244353;
      }*/
      ans[i] +=
          998244353 + anssum[max(i - L[p], 0)] - anssum[max(i - R[p] - 1, 0)];
      ans[i] %= 998244353;
    }

    anssum[i] = anssum[i - 1] + ans[i];
    anssum[i] %= 998244353;
  }
  // rep1(i, N)cout << i << ": " << ans[i] << endl;
  // rep(i, N)cout << "ans" << i << ": " << ans[i] << endl;
  // rep(i, N)cout << "sum" << i << ": " << anssum[i] << endl;
  cout << ans[N] << endl;
  return 0;
}


#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (int)(n); ++i)

using namespace std;
using ll = long long;
const ll mod = 998244353;
int main() {
  ll n, k;
  cin >> n >> k;
  vector<int> l(k), r(k);
  rep(i, k) { cin >> l[i] >> r[i]; }
  vector<int> dp(n + 10);
  dp[1] = 1;
  for (int i = 1; i < n; i++) {
    dp[i] += dp[i - 1];
    dp[i] %= mod;
    rep(j, k) {
      int num = min(i + r[j] + 1, (int)(n + 1));
      dp[i + l[j]] += dp[i];
      dp[i + l[j]] %= mod;
      dp[num] -= dp[i];
      if (dp[num] < 0)
        dp[num] += mod;
    }
  }
  dp[n] %= mod;
  cout << dp[n] << endl;
  return 0;
}

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (int)(n); ++i)

using namespace std;
using ll = long long;
const ll mod = 998244353;
int main() {
  ll n, k;
  cin >> n >> k;
  vector<int> l(k), r(k);
  rep(i, k) { cin >> l[i] >> r[i]; }
  vector<int> dp(n + 10);
  dp[1] = 1;
  for (int i = 1; i < n; i++) {
    dp[i] += dp[i - 1];
    dp[i] %= mod;
    rep(j, k) {
      int num = min(i + r[j] + 1, (int)(n + 1));
      int nu = min(i + l[j], (int)(n + 1));
      dp[nu] += dp[i];
      dp[nu] %= mod;
      dp[num] -= dp[i];
      if (dp[num] < 0)
        dp[num] += mod;
    }
  }
  dp[n] %= mod;
  cout << dp[n] << endl;
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll MOD = 998244353;
void add(ll &a, ll b) {
  a = (a + b) % MOD;
  a = (a + MOD) % MOD;
}
int main() {
  int n, k;
  cin >> n >> k;
  set<int> s;
  vector<ll> dp(n + 1, 0);
  dp[1] = 1;
  for (int i = 0; i < k; i++) {
    int l, r;
    cin >> l >> r;
    for (int j = l; j <= r; j++) {
      s.insert(j);
    }
  }
  for (int i = 1; i < n; i++) {
    if (dp[i] == 0)
      continue;
    for (int ad : s) {
      if (i + ad <= n) {
        dp[i + ad] = (dp[i + ad] + dp[i]) % MOD;
      }
    }
    // for(int d : dp)
    // {
    //     cout << d << endl;
    // }
    // cout << endl;
  }
  cout << (dp[n] + MOD) % MOD << endl;
}

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<int, int>;
ll MOD = 998244353;
void add(int &a, int b) {
  a = (a + b) % MOD;
  a = (a + MOD) % MOD;
}
int main() {
  int n, k;
  cin >> n >> k;
  vector<P> v(k);
  for (int i = 0; i < k; i++) {
    int l, r;
    cin >> l >> r;
    r++;
    v[i] = P(l, r);
  }
  vector<int> dp(n + 1, 0);
  vector<int> num(n + 1, 0);
  dp[1] = 1;
  for (int i = 1; i <= n; i++) {
    add(num[i], num[i - 1]);
    if (i > 1)
      dp[i] = num[i];
    for (int j = 0; j < k; j++) {
      int l = v[j].first;
      int r = v[j].second;
      if (i + l <= n)
        add(num[i + l], dp[i]);
      if (i + r <= n)
        add(num[i + r], -dp[i]);
    }
    // for(int i = 1; i <= n; i++)
    //{
    //     cout << dp[i] << " ";
    // }
    // cout << endl;
    // for(int i = 1; i <= n; i++)
    //{
    //     cout << num[i] << " ";
    // }
    // cout << endl;
    // cout << endl;
  }
  cout << dp[n] << endl;
}


#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;

int mod = 998244353;

int calcA(vector<int> s, vector<int> a, int n) {
  int res = 0;
  rep(i, s.size()) {
    if (n - s[i] >= 0) {
      res += a[n - s[i]];
      res %= mod;
    }
  }
  return res;
}

int main(void) {
  int n, k;
  cin >> n >> k;

  vector<int> s;
  rep(i, k) {
    int l, r;
    cin >> l >> r;
    for (int i = l; i <= r; i++) {
      s.push_back(i);
    }
  }
  sort(s.begin(), s.end());
  // rep(i,s.size()) cout << s[i] << " "; cout << endl;

  vector<int> a(n, 0);
  a[0] = 1;
  for (int i = 1; i < n; i++) {
    a[i] = calcA(s, a, i);
  }
  // rep(i,a.size()) cout << a[i] << " "; cout << endl;
  cout << a[n - 1] << endl;
  return 0;
}

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;

int mod = 998244353;

int main(void) {
  int n, k;
  cin >> n >> k;
  vector<int> l(k), r(k);
  rep(i, k) { cin >> l[i] >> r[i]; }

  vector<int> dp(n + 1);
  vector<int> dpsum(n + 1);
  dp[1] = 1;
  dpsum[1] = 1;
  for (int i = 2; i <= n; ++i) {
    rep(j, k) {
      int li = i - r[j];
      int ri = i - l[j];
      if (ri < 1) {
        continue;
      }
      li = max(li, 1);
      dp[i] += (dpsum[ri] - dpsum[li - 1]) % mod;
      dp[i] %= mod;
    }
    dpsum[i] = (dpsum[i - 1] + dp[i]) % mod;
    dpsum[i] %= mod;
  }
  int ans = (dp[n] + mod) % mod;
  cout << ans << endl;
  return 0;
}


/*
***AUTHOR***
*ADVAITVD99*
*/
#include <bits/stdc++.h>

using namespace std;

int main() {
  clock_t tim;
  tim = clock();
  const long long MOD = 998244353;
  {
    int n, k;
    cin >> n >> k;
    vector<int> coins;
    for (int i = 0; i < k; i++) {
      int L, R;
      cin >> L >> R;
      for (int i = L; i <= R; i++) {
        coins.push_back(i);
      }
    }
    sort(coins.begin(), coins.end());
    long long dp[n + 1];
    fill(dp, dp + n + 1, 0);
    dp[1] = 1;
    for (int i = 2; i < n + 1; i++) {
      for (int j = 0; j < coins.size() && i - coins[j] >= 1; j++) {
        dp[i] = (dp[i] + dp[i - coins[j]]) % MOD;
      }
    }
    cout << dp[n] << endl;
  }

  // tim = clock() - tim;
  // double time_taken = ((double)tim)/CLOCKS_PER_SEC;
  // cout<< fixed << setprecision(3) << time_taken << "seconds" <<endl;

  return 0;
}

/*
***AUTHOR***
*ADVAITVD99*
*/
#include <bits/stdc++.h>

using namespace std;

int main() {
  // clock_t tim;
  // tim = clock();
  const long long MOD = 998244353;
  {
    int n, k;
    cin >> n >> k;
    vector<pair<int, int>> coins;
    for (int i = 0; i < k; i++) {
      int L, R;
      cin >> L >> R;
      R++;
      coins.push_back({L, R});
    }
    // sort(coins.begin(),coins.end());
    long long dp[n];
    fill(dp, dp + n, 0);
    dp[0] = 1;
    dp[1] = -1;
    for (int i = 0; i < n; i++) {
      if (i > 0) {
        dp[i] = (dp[i] + dp[i - 1]) % MOD;
      }
      for (int j = 0; j < k; j++) {
        int l, r;
        l = coins[j].first;
        r = coins[j].second;
        if (i + l < n) {
          dp[i + l] = (dp[i + l] + dp[i]) % MOD;
        }
        if (i + r < n) {
          dp[i + r] = (dp[i + r] - dp[i]);
        }
      }
    }
    dp[n - 1] = dp[n - 1] % MOD;
    if (dp[n - 1] < 0) {
      dp[n - 1] += MOD;
    }
    cout << dp[n - 1] << endl;
  }

  // tim = clock() - tim;
  // double time_taken = ((double)tim)/CLOCKS_PER_SEC;
  // cout<< fixed << setprecision(3) << time_taken << "seconds" <<endl;

  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int(i) = 0; (i) < (n); (i)++)
#define FOR(i, m, n) for (int(i) = (m); (i) < (n); (i)++)
#define All(v) (v).begin(), (v).end()
#define pb push_back
#define MP(a, b) make_pair((a), (b))
template <class T> vector<T> make_vec(size_t a, T val) {
  return vector<T>(a, val);
}
template <class... Ts> auto make_vec(size_t a, Ts... ts) {
  return vector<decltype(make_vec(ts...))>(a, make_vec(ts...));
}
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using Graph = vector<vector<int>>;
template <typename T> struct edge {
  int to;
  T cost;
  edge(int t, T c) : to(t), cost(c) {}
};
template <typename T> using WGraph = vector<vector<edge<T>>>;
const int INF = 1 << 30;
const ll LINF = 1LL << 60;
const int MOD = 998244353;

template <uint_fast64_t MOD> class ModInt {
  using u64 = uint_fast64_t;

public:
  u64 val;

  ModInt(const u64 x = 0) : val((x + MOD) % MOD) {}
  constexpr u64 &value() { return val; }
  constexpr ModInt operator-() { return val ? MOD - val : 0; }
  constexpr ModInt operator+(const ModInt &rhs) const {
    return ModInt(*this) += rhs;
  }
  constexpr ModInt operator-(const ModInt &rhs) const {
    return ModInt(*this) -= rhs;
  }
  constexpr ModInt operator*(const ModInt &rhs) const {
    return ModInt(*this) *= rhs;
  }
  constexpr ModInt operator/(const ModInt &rhs) const {
    return ModInt(*this) /= rhs;
  }
  constexpr ModInt &operator+=(const ModInt &rhs) {
    val += rhs.val;
    if (val >= MOD) {
      val -= MOD;
    }
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &rhs) {
    if (val < rhs.val) {
      val += MOD;
    }
    val -= rhs.val;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &rhs) {
    val = val * rhs.val % MOD;
    return *this;
  }

  constexpr ModInt &operator/=(const ModInt &rhs) {
    *this *= rhs.inv();
    return *this;
  }

  constexpr bool operator==(const ModInt &rhs) { return this->val == rhs.val; }
  constexpr bool operator!=(const ModInt &rhs) { return this->val != rhs.val; }
  friend constexpr ostream &operator<<(ostream &os, const ModInt<MOD> &x) {
    return os << x.val;
  }
  friend constexpr istream &operator>>(istream &is, ModInt<MOD> &x) {
    return is >> x.val;
  }

  constexpr ModInt inv() const { return ModInt(*this).pow(MOD - 2); }

  constexpr ModInt pow(ll e) const {
    u64 x = 1, p = val;
    while (e > 0) {
      if (e % 2 == 0) {
        p = (p * p) % MOD;
        e /= 2;
      } else {
        x = (x * p) % MOD;
        e--;
      }
    }
    return ModInt(x);
  }
};

using mint = ModInt<MOD>;

// Range Sum Query by LazySegmentTree
struct LazySegTree {
private:
  int n;
  vector<mint> node, lazy;

public:
  LazySegTree(vector<mint> v) {
    int sz = (int)v.size();
    n = 1;
    while (n < sz)
      n *= 2;
    node.resize(2 * n - 1);
    lazy.resize(2 * n - 1, 0);

    for (int i = 0; i < sz; i++)
      node[i + n - 1] = v[i];
    for (int i = n - 2; i >= 0; i--)
      node[i] = node[i * 2 + 1] + node[i * 2 + 2];
  }

  // k番目のノードについて遅延評価
  void eval(int k, int l, int r) {
    // 遅延配列を見て空でなかったら値を伝播
    if (lazy[k] != 0) {
      node[k] += lazy[k];
      // 最下段かどうかチェック
      // 伝播
      if (r - l > 1) {
        lazy[2 * k + 1] += lazy[k] / 2;
        lazy[2 * k + 2] += lazy[k] / 2;
      }
    }

    // 伝播の終了
    lazy[k] = 0;
  }

  mint at(int k) { return getsum(k, k + 1); }

  // [a,b)区間加算
  void add(int a, int b, mint x, int k = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    // まず評価
    eval(k, l, r);
    // 範囲外なら何もしない
    if (b <= l || r <= a)
      return;

    // 完全に被覆 遅延配列に値を入れ評価
    if (a <= l && r <= b) {
      lazy[k] += mint(r - l) * x;
      eval(k, l, r);
    }
    // そうでないとき 子コードの値を再帰的に計算して計算済みの値をもってくる
    else {
      add(a, b, x, 2 * k + 1, l, (l + r) / 2);
      add(a, b, x, 2 * k + 2, (l + r) / 2, r);
      node[k] = node[2 * k + 1] + node[2 * k] + 2;
    }
  }

  // [a,b)区間取得
  mint getsum(int a, int b, int k = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    if (b <= l || r <= a)
      return 0;

    // まず評価
    eval(k, l, r);
    if (a <= l && r <= b)
      return node[k];
    mint vl = getsum(a, b, 2 * k + 1, l, (l + r) / 2);
    mint vr = getsum(a, b, 2 * k + 2, (l + r) / 2, r);
    return vl + vr;
  }
};

int main() {
  int N, K;
  cin >> N >> K;
  vector<int> L(K), R(K);
  rep(i, K) cin >> L[i] >> R[i];
  auto dp = make_vec(N + 1, mint(0));
  dp[0] = 1;
  LazySegTree segtree(dp);
  for (int i = 0; i < N; i++) {
    dp[i] = segtree.at(i);
    for (int j = 0; j < K; j++) {
      segtree.add(min(N, i + L[j]), min(N + 1, i + R[j] + 1), dp[i]);
    }
  }
  cout << dp[N - 1] << endl;
}

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int(i) = 0; (i) < (n); (i)++)
#define FOR(i, m, n) for (int(i) = (m); (i) < (n); (i)++)
#define All(v) (v).begin(), (v).end()
#define pb push_back
#define MP(a, b) make_pair((a), (b))
template <class T> vector<T> make_vec(size_t a, T val) {
  return vector<T>(a, val);
}
template <class... Ts> auto make_vec(size_t a, Ts... ts) {
  return vector<decltype(make_vec(ts...))>(a, make_vec(ts...));
}
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using Graph = vector<vector<int>>;
template <typename T> struct edge {
  int to;
  T cost;
  edge(int t, T c) : to(t), cost(c) {}
};
template <typename T> using WGraph = vector<vector<edge<T>>>;
const int INF = 1 << 30;
const ll LINF = 1LL << 60;
const int MOD = 998244353;

template <uint_fast64_t MOD> class ModInt {
  using u64 = uint_fast64_t;

public:
  u64 val;

  ModInt(const u64 x = 0) : val((x + MOD) % MOD) {}
  constexpr u64 &value() { return val; }
  constexpr ModInt operator-() { return val ? MOD - val : 0; }
  constexpr ModInt operator+(const ModInt &rhs) const {
    return ModInt(*this) += rhs;
  }
  constexpr ModInt operator-(const ModInt &rhs) const {
    return ModInt(*this) -= rhs;
  }
  constexpr ModInt operator*(const ModInt &rhs) const {
    return ModInt(*this) *= rhs;
  }
  constexpr ModInt operator/(const ModInt &rhs) const {
    return ModInt(*this) /= rhs;
  }
  constexpr ModInt &operator+=(const ModInt &rhs) {
    val += rhs.val;
    if (val >= MOD) {
      val -= MOD;
    }
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &rhs) {
    if (val < rhs.val) {
      val += MOD;
    }
    val -= rhs.val;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &rhs) {
    val = val * rhs.val % MOD;
    return *this;
  }

  constexpr ModInt &operator/=(const ModInt &rhs) {
    *this *= rhs.inv();
    return *this;
  }

  constexpr bool operator==(const ModInt &rhs) { return this->val == rhs.val; }
  constexpr bool operator!=(const ModInt &rhs) { return this->val != rhs.val; }
  friend constexpr ostream &operator<<(ostream &os, const ModInt<MOD> &x) {
    return os << x.val;
  }
  friend constexpr istream &operator>>(istream &is, ModInt<MOD> &x) {
    return is >> x.val;
  }

  constexpr ModInt inv() const { return ModInt(*this).pow(MOD - 2); }

  constexpr ModInt pow(ll e) const {
    u64 x = 1, p = val;
    while (e > 0) {
      if (e % 2 == 0) {
        p = (p * p) % MOD;
        e /= 2;
      } else {
        x = (x * p) % MOD;
        e--;
      }
    }
    return ModInt(x);
  }
};

using mint = ModInt<MOD>;

// Range Sum Query by LazySegmentTree
struct LazySegTree {
private:
  int n;
  vector<mint> node, lazy;

public:
  LazySegTree(vector<mint> v) {
    int sz = (int)v.size();
    n = 1;
    while (n < sz)
      n *= 2;
    node.resize(2 * n - 1);
    lazy.resize(2 * n - 1, 0);

    for (int i = 0; i < sz; i++)
      node[i + n - 1] = v[i];
    for (int i = n - 2; i >= 0; i--)
      node[i] = node[i * 2 + 1] + node[i * 2 + 2];
  }

  // k番目のノードについて遅延評価
  void eval(int k, int l, int r) {
    // 遅延配列を見て空でなかったら値を伝播
    if (lazy[k] != 0) {
      node[k] += lazy[k];
      // 最下段かどうかチェック
      // 伝播
      if (r - l > 1) {
        lazy[2 * k + 1] += lazy[k] / 2;
        lazy[2 * k + 2] += lazy[k] / 2;
      }
    }

    // 伝播の終了
    lazy[k] = 0;
  }

  mint at(int k) { return getsum(k, k + 1); }

  // [a,b)区間加算
  void add(int a, int b, mint x, int k = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    // まず評価
    eval(k, l, r);
    // 範囲外なら何もしない
    if (b <= l || r <= a)
      return;

    // 完全に被覆 遅延配列に値を入れ評価
    if (a <= l && r <= b) {
      lazy[k] += mint(r - l) * x;
      eval(k, l, r);
    }
    // そうでないとき 子コードの値を再帰的に計算して計算済みの値をもってくる
    else {
      add(a, b, x, 2 * k + 1, l, (l + r) / 2);
      add(a, b, x, 2 * k + 2, (l + r) / 2, r);
      node[k] = node[2 * k + 1] + node[2 * k] + 2;
    }
  }

  // [a,b)区間取得
  mint getsum(int a, int b, int k = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    if (b <= l || r <= a)
      return 0;

    // まず評価
    eval(k, l, r);
    if (a <= l && r <= b)
      return node[k];
    mint vl = getsum(a, b, 2 * k + 1, l, (l + r) / 2);
    mint vr = getsum(a, b, 2 * k + 2, (l + r) / 2, r);
    return vl + vr;
  }
};

int main() {
  int N, K;
  cin >> N >> K;
  vector<int> L(K), R(K);
  rep(i, K) cin >> L[i] >> R[i];
  auto dp = make_vec(N + 1, mint(0));
  dp[0] = 1;
  vector<mint> imos(N + 1);
  mint sum = 1;
  for (int i = 0; i < N; i++) {
    sum += imos[i];
    dp[i] = sum;
    for (int j = 0; j < K; j++) {
      imos[min(N, i + L[j])] += dp[i];
      imos[min(N, i + R[j] + 1)] -= dp[i];
    }
  }
  cout << imos[N - 1] << endl;
}


#include <bits/stdc++.h>
using namespace std;

using i64 = long long;
using u64 = unsigned long long;

const int mod = 998244353;

void __print() { cerr << "]\\n"; }

template <typename T, typename... V> void __print(T t, V... v) {
  cerr << t;
  if (sizeof...(v))
    cerr << ", ";
  __print(v...);
}

#define dbg(x...) cerr << "[" << #x << "] = [", __print(x)
#define FASTIO ios_base::sync_with_stdio(false), cin.tie(NULL)

i64 dp[300000];

int main() {
  int n, k;
  scanf("%d%d", &n, &k);
  vector<int> steps;
  while (k--) {
    int l, r;
    scanf("%d%d", &l, &r);
    for (int i = l; i <= r; i++)
      steps.push_back(i);
  }
  dp[1] = 1;
  sort(steps.begin(), steps.end());
  int sz = steps.size();
  for (int i = 1; i <= n; i++) {
    for (int j = 0; j < sz; j++) {
      if (i + steps[j] > n)
        break;
      dp[i + steps[j]] += dp[i];
      dp[i + steps[j]] %= mod;
    }
  }
  printf("%lld\\n", dp[n]);
}

#include <bits/stdc++.h>
using namespace std;

using i64 = long long;
using u64 = unsigned long long;

const int mod = 998244353;

void __print() { cerr << "]\\n"; }

template <typename T, typename... V> void __print(T t, V... v) {
  cerr << t;
  if (sizeof...(v))
    cerr << ", ";
  __print(v...);
}

#define dbg(x...) cerr << "[" << #x << "] = [", __print(x)
#define FASTIO ios_base::sync_with_stdio(false), cin.tie(NULL)

i64 dp[300000];
i64 q_sum[1000000];

int main() {
  int n, k;
  scanf("%d%d", &n, &k);
  vector<pair<int, int>> v;
  while (k--) {
    int l, r;
    scanf("%d%d", &l, &r);
    v.push_back({l, r});
  }
  dp[1] = 1;
  for (int i = 1; i <= n; i++) {
    q_sum[i] += q_sum[i - 1];
    q_sum[i] %= mod;
    dp[i] += q_sum[i];
    dp[i] %= mod;
    for (auto p : v) {
      int x, y;
      tie(x, y) = p;
      q_sum[i + x] += dp[i];
      q_sum[i + x] %= mod;
      q_sum[i + y + 1] -= dp[i];
      q_sum[i + y + 1] %= mod;
    }
  }
  // for(int i = 1; i <= n; i++) dbg(dp[i]);
  // for(int i = 1; i <= n; i++) dbg(q_sum[i]);
  dp[n] %= mod;
  dp[n] += mod;
  dp[n] %= mod;
  printf("%lld\\n", dp[n]);
}


#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 5;
const int mod = 998244353;

int n;
int k;
int mem[N];
bool did[N];
vector<int> v;

int go(int poi) {
  if (poi == n)
    return 1;
  if (poi > n)
    return 0;
  int &ret = mem[poi];
  if (~mem[poi])
    return mem[poi];
  ret = 0;
  for (int i = 0; i < v.size(); i++) {
    if (v[i] + poi <= n) {
      ret = ret + go(poi + v[i]);
      ret %= mod;
    } else {
      break;
    }
  }
  return ret;
}

int main() {
  scanf("%d%d", &n, &k);
  memset(mem, -1, sizeof mem);
  for (int i = 1; i <= k; i++) {
    int l, r;
    scanf("%d%d", &l, &r);
    for (int i = l; i <= r; i++)
      v.push_back(i);
  }
  sort(v.begin(), v.end());
  for (int i = n; i > 1; i--)
    go(i);
  printf("%d\\n", go(1));
}

#include <bits/stdc++.h>

using namespace std;

const int N = 3e5 + 5;
const int mod = 998244353;

int n;
int k;
long long dp[N];
long long cm[N];
pair<int, int> pp[N];

int main() {
  scanf("%d%d", &n, &k);
  for (int i = 1; i <= k; i++) {
    int l, r;
    scanf("%d%d", &l, &r);
    pp[i] = {l, r};
  }
  dp[n] = 1;
  cm[n] = 1;
  for (int i = n - 1; i >= 1; i--) {
    for (int j = 1; j <= k; j++) {
      dp[i] += cm[i + pp[j].first] + mod + mod;
      dp[i] -= cm[i + pp[j].second + 1];
      dp[i] %= mod;
    }
    // cout << dp[i] << " ";
    cm[i] = dp[i] + cm[i + 1];
    cm[i] %= mod;
  }
  printf("%lld\\n", dp[1]);
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < n; i++)
#define repr(i, n) for (int i = n - 1; i >= 0; i--)
#define ALL(x) x.begin(), x.end()
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvl = vector<vll>;
const int mod = 998244353;
const int INF = 2e9;
const int MAX = 1e6;

struct unionfind {
  vector<int> parent; // 各要素の親のindex(根の場合は-1)
  vector<int> diff_weight; // 各要素の親要素との重さの差分(根の場合は0)
  unionfind(int n) {
    parent.resize(n, -1);
    diff_weight.resize(n, 0);
  }
  int root(int x) { // 要素xの属する集合の根のindex(要素xが根の場合はx)
    if (parent[x] < 0)
      return x;
    int r = root(parent[x]);
    diff_weight[x] += diff_weight[parent[x]];
    return parent[x] = r;
  }
  int weight(int x) { // 要素xとその親要素との重さの差分
    root(x);
    return diff_weight[x];
  }
  void merge(int x, int y) { // 要素xとyを共通の集合に結合
    x = root(x), y = root(y);
    if (x == y)
      return;
    if (parent[x] > parent[y]) {
      swap(x, y);
    }
    parent[x] += parent[y];
    parent[y] = x;
  }
  void merge(int x, int y, int w) { // 要素xとyを共通の集合に結合
    w += weight(x), w -= weight(y);
    x = root(x), y = root(y);
    if (x == y)
      return;
    if (parent[x] > parent[y]) {
      swap(x, y);
      w *= -1;
    }
    parent[x] += parent[y];
    parent[y] = x;
    diff_weight[y] = w;
  }
  bool common(int x, int y) { // 要素xとyが共通の集合に属するか
    return root(x) == root(y);
  }
  int size(int x) { // 要素xの属する集合の大きさ
    return -parent[root(x)];
  }
  int diff(int x, int y) { // 要素xとyの重さの差分
    return weight(y) - weight(x);
  }
};
struct edge {
  int from, to, cost;
};
struct graph {
  int n;
  vector<vector<edge>> G;
  vector<bool> visited;
  vector<int> indeg;
  graph(int _n) {
    n = _n;
    G.resize(n);
    visited.resize(n, false);
    indeg.resize(n, 0);
  }
  void add_edge(int from, int to, int cost) {
    G[from].push_back({from, to, cost});
    indeg[to]++;
  }
  void dfs(int s) {
    visited[s] = true;
    for (edge e : G[s]) {
      if (not visited[e.to])
        continue;
      dfs(e.to);
    }
  }
  void dfs(int s, int i, int _n) { // 深さ制限探索
    visited[s] = true;
    if (i == _n)
      return;
    for (edge e : G[s]) {
      if (visited[e.to])
        continue;
      dfs(e.to, i + 1, _n);
    }
  }
  void dfs(int cur, int prev, bool &closed) { // 閉路の検出
    visited[cur] = true;
    for (edge e : G[cur]) {
      if (not visited[e.to]) {
        dfs(e.to, cur, closed);
      } else if (e.to != prev) {
        closed = true;
      }
    }
  }
  void bfs(int s) {
    queue<int> q;
    q.push(s);
    visited[s] = true;
    while (not q.empty()) {
      int cur = q.front();
      for (edge e : G[cur]) {
        if (not visited[e.to])
          continue;
        q.push(e.to);
        visited[e.to] = true;
      }
    }
  }
  void dijkstra(int s, vector<int> &dist) {
    using pii = pair<int, int>;
    dist.resize(n, INF);
    dist[s] = 0;
    priority_queue<pii, vector<pii>, greater<pii>> pq;
    pq.push({dist[s], s});
    while (not pq.empty()) {
      int cur = pq.top().second;
      pq.pop();
      for (edge e : G[cur]) {
        if (dist[e.to] > dist[cur] + e.cost) {
          dist[e.to] = dist[cur] + e.cost;
          pq.push({dist[e.to], e.to});
        }
      }
    }
  }
  void bellman_ford(int s, vector<int> &dist, bool &negative) {
    fill(visited.begin(), visited.end(), false);
    dfs(s);
    dist.resize(n, INF);
    dist[s] = 0;
    for (int i = 0; i < n; i++) {
      for (int u = 0; u < n; u++) {
        for (edge e : G[u]) {
          if (not visited[e.to])
            continue;
          if (dist[e.to] > dist[u] + e.cost) {
            dist[e.to] = dist[u] + e.cost;
            if (i == n - 1) {
              negative = true;
              return;
            }
          }
        }
      }
    }
  }
  void warshall_floyd(vector<vector<int>> &dist, bool &negative) {
    dist.resize(n, vector<int>(n, INF));
    for (int i = 0; i < n; i++) {
      for (edge e : G[i]) {
        dist[i][e.to] = e.cost;
      }
      dist[i][i] = 0;
    }
    for (int k = 0; k < n; k++) {
      for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
          if (dist[i][k] == INF or dist[k][j] == INF)
            continue;
          if (dist[i][j] > dist[i][k] + dist[k][j]) {
            dist[i][j] = dist[i][k] + dist[k][j];
          }
          if (i == j and dist[i][j] < 0) {
            negative = true;
            return;
          }
        }
      }
    }
  }
  static bool comp(const edge &e1, const edge &e2) { return e1.cost < e2.cost; }
  void kruskal(vector<edge> &edges, int &sum) {
    unionfind mst(n);
    sort(edges.begin(), edges.end(), comp);
    int m = edges.size();
    sum = 0;
    for (int i = 0; i < m; i++) {
      edge e = edges[i];
      if (not mst.common(e.from, e.to)) {
        mst.merge(e.from, e.to);
        sum += e.cost;
      }
    }
  }
  void topological(vector<int> &t) {
    queue<int> q;
    for (int i = 0; i < n; i++) {
      if (indeg[i] == 0) {
        q.push(i);
      }
    }
    while (not q.empty()) {
      int cur = q.front();
      q.pop();
      t.push_back(cur);
      for (edge e : G[cur]) {
        indeg[e.to]--;
        if (indeg[e.to] == 0) {
          q.push(e.to);
        }
      }
    }
  }
};
template <typename T> struct cusum {
  int n;
  vector<T> s;
  cusum(vector<T> &a) {
    n = a.size();
    s.resize(n + 1);
    s[0] = 0;
    for (int i = 1; i <= n; i++) {
      s[i] = s[i - 1] + a[i - 1];
    }
  }
  T sum(int a, int b) { // 半開区間[a,b)の和(0-indexed)
    return s[b] - s[a];
  }
};
template <typename T> struct BIT {
  int MAX;
  vector<T> bit;
  BIT(int n) {
    MAX = n;
    bit.resize(MAX + 1, 0);
  }
  void add(int i, int x) { // i番目(1-indexed)に値xを追加
    while (i <= MAX) {
      bit[i] += x;
      i += i & -i;
    }
  }
  T sum(int i) { // 閉区間[1,i]の和
    T s = 0;
    while (i > 0) {
      s += bit[i];
      i -= i & -i;
    }
    return s;
  }
  T rsq(int a, int b) { // 閉区間[a,b]の和
    return sum(b) - sum(a - 1);
  }
};
template <typename T> bool is_prime(T x) { // 素数判定
  if (x < 2)
    return false;
  for (T i = 2; i * i <= x; i++) {
    if (x % i == 0)
      return false;
  }
  return true;
}
template <typename T> void prime_fact(T x, vector<T> &factor) { // 素因数分解
  for (T i = 2; i * i <= x; i++) {
    while (x % i == 0) {
      factor.push_back(i);
      x /= i;
    }
  }
  if (x != 1) {
    factor.push_back(x);
  }
}
struct erat {
  int MAX;
  vector<int> seive;
  erat(int n) { // エラトステネスのふるい
    MAX = n;
    seive.resize(MAX + 1);
    for (int i = 0; i <= MAX; i++) {
      seive[i] = i;
    }
    for (int i = 2; i <= MAX; i++) {
      if (seive[i] == i) { // seive[i]はiの最大の素因数
        for (int j = i + i; j <= MAX; j += i) {
          seive[j] = i;
        }
      }
    }
  }
  void fact(int x, vector<int> &factor) { // 高速素因数分解
    if (x < 2)
      return;
    while (x > 1 and x % seive[x] == 0) {
      factor.push_back(seive[x]);
      x /= seive[x];
    }
    reverse(factor.begin(), factor.end());
  }
  bool is_prime(int x) { // 素数判定
    if (x >= 2 and seive[x] == x)
      return true;
    return false;
  }
};
template <typename T>
T gcd(T a, T b) { // 整数aとbの最大公約数（ユークリッドの互除法）
  if (b == 0)
    return a;
  return gcd(b, a % b);
}
template <typename T> T gcd(vector<T> &a) { //  3つ以上の整数の最大公約数
  int n = (int)a.size();
  T r;
  for (int i = 0; i < n; i++) {
    if (i == 0)
      r = a[i];
    r = gcd(r, a[i]);
  }
  return r;
}
template <typename T> T lcm(T a, T b) { // 整数aとbの最小公倍数
  return a / gcd(a, b) * b;
}
template <typename T> T lcm(vector<T> &a) { // 3つ以上の整数の最小公倍数
  int n = (int)a.size();
  T r = 1;
  for (int i = 0; i < n; i++) {
    r = lcm(r, a[i]);
  }
  return r;
}
template <typename T> T digit_sum(T n) { // 整数nの格桁の和
  T sum = 0;
  while (n > 0) {
    sum += n % 10;
    n /= 10;
  }
  return sum;
}
template <typename T> T digit_sum(string s) { // 整数nの格桁の和
  int n = (int)s.size();
  T sum = 0;
  for (int i = 0; i < n; i++) {
    sum += s[i] - '0';
  }
  return sum;
}
int eular(int n) { // nと互いに素であるn以下の自然数の個数
  int p = n;
  for (int i = 2; i * i <= n; i++) {
    if (n % i == 0) {
      p -= p / i;
      while (n % i == 0)
        n /= i;
    }
  }
  if (n > 1)
    p -= p / n;
  return p;
}
template <typename T> bool is_triangle(T a, T b, T c) { // 三角形の成立条件
  if (a + b > c && b + c > a && c + a > b)
    return true;
  else
    return false;
}
template <typename T> struct combination {
  int MAX;
  vector<T> f;
  vector<vector<T>> dp;
  combination(int _n) {
    MAX = _n;
    f.resize(MAX + 1, 0);
    for (int i = 0; i <= MAX; i++) {
      if (i == 0)
        f[i] = 1;
      else
        f[i] = i * f[i - 1] % mod;
    }
    dp.resize(MAX + 1, vector<T>(MAX + 1, 0));
  }
  T power(int m, int n) { // m^n
    if (n == 0)
      return 1;
    if (n % 2 == 1)
      return m * power(m, n - 1) % mod;
    T r = power(m, n / 2);
    return r * r % mod;
  }
  T inv(int a, int b) { // a / b % mod
    return a * power(b, mod - 2) % mod;
  }
  T fact(int n) { // n!
    return f[n];
  }
  T perm(int n, int r) { // nPr
    if (n < r)
      return 0;
    return inv(fact(n), fact(n - r));
  }
  T comb(int n, int r) { // nCr
    if (n < r)
      return 0;
    return inv(perm(n, r), fact(r));
  }
  T pie(int n, int k) { // 包除原理
    T s = 0;
    for (int i = 0; i < k; i++) {
      s += power(-1, i) * comb(k, i) * power(k - i, n);
      s %= mod;
      if (s < 0)
        s += mod;
    }
    return s;
  }
  T part(int n, int k) { // 分割数
    if (n < 0)
      return 0;
    if (n == 0 || k == 1)
      return dp[n][k] = 1;
    if (dp[n][k] != 0)
      return dp[n][k];
    return dp[n][k] = (part(n, k - 1) + part(n - k, k)) % mod;
  }
  T stir(int n, int k) { // スターリング数
    if (n < k || (n > 0 && k == 0))
      return 0;
    if (n == k || k == 1)
      return dp[n][k] = 1;
    if (dp[n][k] != 0)
      return dp[n][k];
    return dp[n][k] = (stir(n - 1, k - 1) + k * stir(n - 1, k)) % mod;
  }
  T bell(int n, int k) { // ベル数
    T s = 0;
    for (int i = 0; i <= k; i++) {
      s += stir(n, i);
      s %= mod;
    }
    return s;
  }
};

vector<int> s;
vector<ll> dp(200001);

ll rec(int i) {
  if (i < 1)
    return 0;
  if (dp[i] != 0)
    return dp[i];
  if (i == 1)
    return dp[i] = 1;
  ll r = 0;
  rep(x, (int)s.size()) {
    r += rec(i - s[x]);
    r %= mod;
  }
  return dp[i] = r;
}

int main() {
  int n, k;
  cin >> n >> k;
  rep(i, k) {
    int l, r;
    cin >> l >> r;
    for (int j = l; j <= r; j++) {
      s.push_back(j);
    }
  }
  sort(ALL(s));
  for (int i = 1; i <= n; i++) {
    if (i == 1)
      dp[i] = 1;
    rep(x, (int)s.size()) {
      if (i + s[x] <= n) {
        dp[i + s[x]] += dp[i];
        dp[i + s[x]] %= mod;
      } else {
        break;
      }
    }
  }
  // cout << rec(n) << endl;
  cout << dp[n] << endl;
}

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < n; i++)
using ll = long long;

const int mod = 998244353;

ll dp[200010], cu[200010];
int l[10], r[10];

int main() {
  int n, k;
  cin >> n >> k;
  rep(i, k) { cin >> l[i] >> r[i]; }
  dp[1] = 1;
  dp[2] = -1;
  for (int i = 1; i <= n; i++) {
    dp[i] += dp[i - 1];
    dp[i] %= mod;
    rep(j, k) {
      if (i + l[j] <= n) {
        dp[i + l[j]] += dp[i];
        dp[i + l[j]] %= mod;
      }
      if (i + r[j] + 1 <= n) {
        dp[i + r[j] + 1] -= dp[i];
        dp[i + r[j] + 1] %= mod;
        if (dp[i + r[j] + 1] < 0)
          dp[i + r[j] + 1] += mod;
      }
    }
  }
  cout << dp[n] << endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long LL;
typedef long double ld;
typedef vector<ll> VI;
typedef pair<int, int> P;
#define VV(T) vector<vector<T>>
#define sz(x) int(x.size())
#define PI 3.1415926535897932384626433832795
#define rep(i, n) for (ll i = 0; i < (ll)n; i++)
#define reprev(i, n) for (ll i = (ll)n - 1; i >= 0; i--)
#define ALL(a) (a).begin(), (a).end()
#define rALL(a) (a).rbegin(), (a).rend()
#define c_max(a, b) (((ll)a) > ((ll)b) ? (a) : (b))
#define c_min(a, b) (((ll)a) < ((ll)b) ? (a) : (b))
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
#define vmax(v) *max_element(ALL(v))
#define vmin(v) *min_element(ALL(v))
#define $(x)                                                                   \\
  { cout << #x << " = " << (x) << endl; }
#define fi first
#define se second
#define MAX 100100 // 5
#define MAX2 200100
#define MAX6 1001001        // 6
#define MAX7 10010010       // 7
#define SENTINEL 2000000000 // 9
#define INF 1 << 30
#define INFTY 1LL << 60
#define MAX_INT INT_MAX
#define Endl '\\n'
#define CLR(mat) memset(mat, 0, sizeof(mat))
inline ll GCD(ll a, ll b) { return b ? GCD(b, a % b) : a; } // 最大公約数
inline ll lcm(ll a, ll b) { return a * b / GCD(a, b); }     // 最小公倍数
template <class T> bool contain(const std::string &s, const T &v) {
  return s.find(v) != std::string::npos;
}
const int MOD = 998244353;

inline ll mod_add(ll a, ll b) { return (a + b) % MOD; }
inline ll mod_sub(ll a, ll b) { return (a + MOD - b) % MOD; }
inline ll mod_mul(ll a, ll b) { return ((a % MOD) * (b % MOD)) % MOD; }
inline ll mod_pow(ll x, ll n, ll mod = (ll)MOD) {
  ll res = 1;
  while (n > 0) {
    if (n & 1)
      res = res * x % mod;
    x = x * x % mod;
    n >>= 1;
  }
  return res;
}
inline ll mod_inv(ll x) { return mod_pow(x, MOD - 2); }
inline ll mod_div(ll a, ll b) { return mod_mul(a, mod_inv(b)); }
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
// vector型から重複を削除 list.erase(unique(ALL(list)),list.end());
// g++ -o a a.cpp -Wall -lm -std=c++17
// push_back -> emplace_back

template <int MOD> struct Fp {
  long long val;
  constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
    if (val < 0)
      val += MOD;
  }
  constexpr int getmod() { return MOD; }
  constexpr Fp operator-() const noexcept { return val ? MOD - val : 0; }
  constexpr Fp operator+(const Fp &r) const noexcept { return Fp(*this) += r; }
  constexpr Fp operator-(const Fp &r) const noexcept { return Fp(*this) -= r; }
  constexpr Fp operator*(const Fp &r) const noexcept { return Fp(*this) *= r; }
  constexpr Fp operator/(const Fp &r) const noexcept { return Fp(*this) /= r; }
  constexpr Fp &operator+=(const Fp &r) noexcept {
    val += r.val;
    if (val >= MOD)
      val -= MOD;
    return *this;
  }
  constexpr Fp &operator-=(const Fp &r) noexcept {
    val -= r.val;
    if (val < 0)
      val += MOD;
    return *this;
  }
  constexpr Fp &operator*=(const Fp &r) noexcept {
    val = val * r.val % MOD;
    return *this;
  }
  constexpr Fp &operator/=(const Fp &r) noexcept {
    long long a = r.val, b = MOD, u = 1, v = 0;
    while (b) {
      long long t = a / b;
      a -= t * b;
      swap(a, b);
      u -= t * v;
      swap(u, v);
    }
    val = val * u % MOD;
    if (val < 0)
      val += MOD;
    return *this;
  }
  constexpr bool operator==(const Fp &r) const noexcept {
    return this->val == r.val;
  }
  constexpr bool operator!=(const Fp &r) const noexcept {
    return this->val != r.val;
  }
  friend constexpr ostream &operator<<(ostream &os, const Fp<MOD> &x) noexcept {
    return os << x.val;
  }
  friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
    if (n == 0)
      return 1;
    auto t = modpow(a, n / 2);
    t = t * t;
    if (n & 1)
      t = t * a;
    return t;
  }
};

// 二項係数ライブラリ
template <class T> struct BiCoef {
  vector<T> fact_, inv_, finv_;
  constexpr BiCoef() {}
  constexpr BiCoef(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
    init(n);
  }
  constexpr void init(int n) noexcept {
    fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
    int MOD = fact_[0].getmod();
    for (int i = 2; i < n; i++) {
      fact_[i] = fact_[i - 1] * i;
      inv_[i] = -inv_[MOD % i] * (MOD / i);
      finv_[i] = finv_[i - 1] * inv_[i];
    }
  }
  constexpr T com(int n, int k) const noexcept {
    if (n < k || n < 0 || k < 0)
      return 0;
    return fact_[n] * finv_[k] * finv_[n - k];
  }
  constexpr T fact(int n) const noexcept {
    if (n < 0)
      return 0;
    return fact_[n];
  }
  constexpr T inv(int n) const noexcept {
    if (n < 0)
      return 0;
    return inv_[n];
  }
  constexpr T finv(int n) const noexcept {
    if (n < 0)
      return 0;
    return finv_[n];
  }
};
using mint = Fp<MOD>;

// 区間加算にも対応した BIT
template <class Abel> struct BIT {
  vector<Abel> dat[2];
  Abel UNITY_SUM = 0; // to be set

  /* [1, n] */
  BIT(int n) { init(n); }
  void init(int n) {
    for (int iter = 0; iter < 2; ++iter)
      dat[iter].assign(n + 1, UNITY_SUM);
  }

  /* a, b are 1-indexed, [a, b) */
  inline void sub_add(int p, int a, Abel x) {
    for (int i = a; i < (int)dat[p].size(); i += i & -i)
      dat[p][i] = dat[p][i] + x;
  }
  inline void add(int a, int b, Abel x) {
    sub_add(0, a, x * -(a - 1));
    sub_add(1, a, x);
    sub_add(0, b, x * (b - 1));
    sub_add(1, b, x * (-1));
  }

  /* a is 1-indexed, [a, b) */
  inline Abel sub_sum(int p, int a) {
    Abel res = UNITY_SUM;
    for (int i = a; i > 0; i -= i & -i)
      res = res + dat[p][i];
    return res;
  }
  inline Abel sum(int a, int b) {
    return sub_sum(0, b - 1) + sub_sum(1, b - 1) * (b - 1) - sub_sum(0, a - 1) -
           sub_sum(1, a - 1) * (a - 1);
  }

  /* debug */
  void print() {
    for (int i = 1; i < (int)dat[0].size(); ++i)
      cout << sum(i, i + 1) << ",";
    cout << endl;
  }
};

int main() {
  ll n, k;
  cin >> n >> k;
  BIT<mint> dp(n + 1);
  vector<P> K;
  rep(i, k) {
    ll l, r;
    cin >> l >> r;
    K.emplace_back(P(l, r));
  }
  dp.add(1, 2, 1);
  for (int i = 2; i < 4 * n; i++) {
    for (int j = 0; j < k; j++) {
      if (i - K[j].fi > 0 && i - K[j].se > 0) {
        dp.add(i, i + 1, dp.sum(i - K[j].se, i - K[j].fi + 1));
      } else if (i - K[j].fi > 0 && i - K[j].se <= 0) {
        dp.add(i, i + 1, dp.sum(1, i - K[j].fi + 1));
      }
    }
  }
  cout << dp.sum(n, n + 1) << endl;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long LL;
typedef long double ld;
typedef vector<ll> VI;
typedef pair<int, int> P;
#define VV(T) vector<vector<T>>
#define sz(x) int(x.size())
#define PI 3.1415926535897932384626433832795
#define rep(i, n) for (ll i = 0; i < (ll)n; i++)
#define reprev(i, n) for (ll i = (ll)n - 1; i >= 0; i--)
#define ALL(a) (a).begin(), (a).end()
#define rALL(a) (a).rbegin(), (a).rend()
#define c_max(a, b) (((ll)a) > ((ll)b) ? (a) : (b))
#define c_min(a, b) (((ll)a) < ((ll)b) ? (a) : (b))
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
#define vmax(v) *max_element(ALL(v))
#define vmin(v) *min_element(ALL(v))
#define $(x)                                                                   \\
  { cout << #x << " = " << (x) << endl; }
#define fi first
#define se second
#define MAX 100100 // 5
#define MAX2 200100
#define MAX6 1001001        // 6
#define MAX7 10010010       // 7
#define SENTINEL 2000000000 // 9
#define INF 1 << 30
#define INFTY 1LL << 60
#define MAX_INT INT_MAX
#define Endl '\\n'
#define CLR(mat) memset(mat, 0, sizeof(mat))
inline ll GCD(ll a, ll b) { return b ? GCD(b, a % b) : a; } // 最大公約数
inline ll lcm(ll a, ll b) { return a * b / GCD(a, b); }     // 最小公倍数
template <class T> bool contain(const std::string &s, const T &v) {
  return s.find(v) != std::string::npos;
}
const int MOD = 998244353;

inline ll mod_add(ll a, ll b) { return (a + b) % MOD; }
inline ll mod_sub(ll a, ll b) { return (a + MOD - b) % MOD; }
inline ll mod_mul(ll a, ll b) { return ((a % MOD) * (b % MOD)) % MOD; }
inline ll mod_pow(ll x, ll n, ll mod = (ll)MOD) {
  ll res = 1;
  while (n > 0) {
    if (n & 1)
      res = res * x % mod;
    x = x * x % mod;
    n >>= 1;
  }
  return res;
}
inline ll mod_inv(ll x) { return mod_pow(x, MOD - 2); }
inline ll mod_div(ll a, ll b) { return mod_mul(a, mod_inv(b)); }
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
// vector型から重複を削除 list.erase(unique(ALL(list)),list.end());
// g++ -o a a.cpp -Wall -lm -std=c++17
// push_back -> emplace_back

template <int MOD> struct Fp {
  long long val;
  constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
    if (val < 0)
      val += MOD;
  }
  constexpr int getmod() { return MOD; }
  constexpr Fp operator-() const noexcept { return val ? MOD - val : 0; }
  constexpr Fp operator+(const Fp &r) const noexcept { return Fp(*this) += r; }
  constexpr Fp operator-(const Fp &r) const noexcept { return Fp(*this) -= r; }
  constexpr Fp operator*(const Fp &r) const noexcept { return Fp(*this) *= r; }
  constexpr Fp operator/(const Fp &r) const noexcept { return Fp(*this) /= r; }
  constexpr Fp &operator+=(const Fp &r) noexcept {
    val += r.val;
    if (val >= MOD)
      val -= MOD;
    return *this;
  }
  constexpr Fp &operator-=(const Fp &r) noexcept {
    val -= r.val;
    if (val < 0)
      val += MOD;
    return *this;
  }
  constexpr Fp &operator*=(const Fp &r) noexcept {
    val = val * r.val % MOD;
    return *this;
  }
  constexpr Fp &operator/=(const Fp &r) noexcept {
    long long a = r.val, b = MOD, u = 1, v = 0;
    while (b) {
      long long t = a / b;
      a -= t * b;
      swap(a, b);
      u -= t * v;
      swap(u, v);
    }
    val = val * u % MOD;
    if (val < 0)
      val += MOD;
    return *this;
  }
  constexpr bool operator==(const Fp &r) const noexcept {
    return this->val == r.val;
  }
  constexpr bool operator!=(const Fp &r) const noexcept {
    return this->val != r.val;
  }
  friend constexpr ostream &operator<<(ostream &os, const Fp<MOD> &x) noexcept {
    return os << x.val;
  }
  friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
    if (n == 0)
      return 1;
    auto t = modpow(a, n / 2);
    t = t * t;
    if (n & 1)
      t = t * a;
    return t;
  }
};

// 二項係数ライブラリ
template <class T> struct BiCoef {
  vector<T> fact_, inv_, finv_;
  constexpr BiCoef() {}
  constexpr BiCoef(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
    init(n);
  }
  constexpr void init(int n) noexcept {
    fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
    int MOD = fact_[0].getmod();
    for (int i = 2; i < n; i++) {
      fact_[i] = fact_[i - 1] * i;
      inv_[i] = -inv_[MOD % i] * (MOD / i);
      finv_[i] = finv_[i - 1] * inv_[i];
    }
  }
  constexpr T com(int n, int k) const noexcept {
    if (n < k || n < 0 || k < 0)
      return 0;
    return fact_[n] * finv_[k] * finv_[n - k];
  }
  constexpr T fact(int n) const noexcept {
    if (n < 0)
      return 0;
    return fact_[n];
  }
  constexpr T inv(int n) const noexcept {
    if (n < 0)
      return 0;
    return inv_[n];
  }
  constexpr T finv(int n) const noexcept {
    if (n < 0)
      return 0;
    return finv_[n];
  }
};
using mint = Fp<MOD>;

// 区間加算にも対応した BIT
template <class Abel> struct BIT {
  vector<Abel> dat[2];
  Abel UNITY_SUM = 0; // to be set

  /* [1, n] */
  BIT(int n) { init(n); }
  void init(int n) {
    for (int iter = 0; iter < 2; ++iter)
      dat[iter].assign(n + 1, UNITY_SUM);
  }

  /* a, b are 1-indexed, [a, b) */
  inline void sub_add(int p, int a, Abel x) {
    for (int i = a; i < (int)dat[p].size(); i += i & -i)
      dat[p][i] = dat[p][i] + x;
  }
  inline void add(int a, int b, Abel x) {
    sub_add(0, a, x * -(a - 1));
    sub_add(1, a, x);
    sub_add(0, b, x * (b - 1));
    sub_add(1, b, x * (-1));
  }

  /* a is 1-indexed, [a, b) */
  inline Abel sub_sum(int p, int a) {
    Abel res = UNITY_SUM;
    for (int i = a; i > 0; i -= i & -i)
      res = res + dat[p][i];
    return res;
  }
  inline Abel sum(int a, int b) {
    return sub_sum(0, b - 1) + sub_sum(1, b - 1) * (b - 1) - sub_sum(0, a - 1) -
           sub_sum(1, a - 1) * (a - 1);
  }

  /* debug */
  void print() {
    for (int i = 1; i < (int)dat[0].size(); ++i)
      cout << sum(i, i + 1) << ",";
    cout << endl;
  }
};

int main() {
  ll n, k;
  cin >> n >> k;
  BIT<mint> dp(4 * n);
  vector<P> K;
  rep(i, k) {
    ll l, r;
    cin >> l >> r;
    K.emplace_back(P(l, r));
  }
  dp.add(1, 2, 1);
  for (int i = 2; i < 2 * n; i++) {
    for (int j = 0; j < k; j++) {
      if (i - K[j].fi > 0 && i - K[j].se > 0) {
        dp.add(i, i + 1, dp.sum(i - K[j].se, i - K[j].fi + 1));
      } else if (i - K[j].fi > 0 && i - K[j].se <= 0) {
        dp.add(i, i + 1, dp.sum(1, i - K[j].fi + 1));
      }
    }
  }
  cout << dp.sum(n, n + 1) << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define MOD 998244353

int main() {
  int n, k;
  cin >> n >> k;
  vector<pair<int, int>> A;
  for (int i = 0; i < k; ++i) {
    int l, r;
    cin >> l >> r;
    A.push_back({l, r});
  }
  sort(A.begin(), A.end());
  vector<int> jump;
  for (int i = 0; i < A.size(); ++i) {
    for (int j = A[i].first; j <= A[i].second; ++j) {
      jump.push_back(j);
    }
  }
  vector<long long> Dp(n, 0);
  Dp[0] = 1;
  for (int i = 0; i < n; ++i) {
    for (int x : jump) {
      if (i + x < n)
        Dp[i + x] = (Dp[i + x] + Dp[i]) % MOD;
      else
        break;
    }
  }
  cout << Dp[n - 1] << "\\n";
}

#include <bits/stdc++.h>
using namespace std;
#define MOD 998244353

int main() {
  int n, k;
  cin >> n >> k;
  vector<pair<int, int>> A;
  for (int i = 0; i < k; ++i) {
    int l, r;
    cin >> l >> r;
    A.push_back({l, r});
  }
  sort(A.begin(), A.end());
  vector<long long> Dp(n + 1, 0);
  Dp[0] = 1;
  Dp[1] = -1;
  for (int i = 0; i < n; ++i) {
    if (i > 0)
      Dp[i] = (Dp[i] + Dp[i - 1]) % MOD;
    for (int j = 0; j < k; ++j) {
      int l = A[j].first, r = A[j].second;
      if (i + l < n)
        Dp[i + l] = (Dp[i + l] + Dp[i]) % MOD;
      if (i + r < n) {
        Dp[i + r + 1] = (Dp[i + r + 1] - Dp[i]) % MOD;
        if (Dp[i + r + 1] < 0)
          Dp[i + r + 1] += MOD;
      }
    }
  }
  cout << Dp[n - 1] << "\\n";
}


#include <bits/stdc++.h>
using namespace std;
int main() {
  uint64_t n;
  int k;
  cin >> n >> k;
  vector<uint64_t> l(k);
  vector<uint64_t> r(k);
  for (int i = 0; i < k; i++) {
    cin >> l[i] >> r[i];
  }
  sort(l.begin(), l.end());
  sort(r.begin(), r.end());
  vector<uint64_t> a(n + 1, 0);
  a[1] = 1;
  bool bo;
  for (int i = l[0]; i <= n; i++) {
    bo = true;
    for (int j = 0; j < k; j++) {
      for (int d = l[j]; d <= r[j]; d++) {
        if (d < i) {
          a[i] += a[i - d];
          a[i] %= 998244353;
        } else {
          bo = false;
          break;
        }
      }
      if (!bo) {
        break;
      }
    }
  }
  cout << a[n] << endl;
}

#include <bits/stdc++.h>
using namespace std;
int main() {
  int n, k;
  cin >> n >> k;
  vector<int> l(k), r(k);
  for (int i = 0; i < k; i++) {
    cin >> l[i] >> r[i];
  }
  sort(l.begin(), l.end());
  sort(r.begin(), r.end());
  vector<int64_t> a(n + 1, 0);
  a[1] = 1;
  a[2] = -1;
  int64_t dpsum = 0;
  for (int i = 1; i < n; i++) {
    dpsum += a[i];
    dpsum %= 998244353;
    for (int j = 0; j < k; j++) {
      if (i + l[j] <= n) {
        a[i + l[j]] += dpsum;
        a[i + l[j]] %= 998244353;
      }
      if (i + r[j] + 1 <= n) {
        a[i + r[j] + 1] -= dpsum;
        a[i + r[j] + 1] %= 998244353;
      }
    }
  }
  uint64_t sum = accumulate(a.begin(), a.end(), 0LL) % 998244353;
  cout << sum << endl;
}


#define _USE_MATH_DEFINES

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using ld = long double;

constexpr ll MOD = 998244353;

#ifndef ONLINE_JUDGE
template <class T, class U>
ostream &operator<<(ostream &o, const map<T, U> &obj) {
  o << "{";
  for (auto &x : obj)
    o << " (" << x.first << " : " << x.second << ")"
      << ",";
  o << " }";
  return o;
}
template <class T> ostream &operator<<(ostream &o, const set<T> &obj) {
  o << "{";
  for (auto itr = obj.begin(); itr != obj.end(); ++itr)
    o << (itr != obj.begin() ? ", " : "") << *itr;
  o << "}";
  return o;
}
template <class T> ostream &operator<<(ostream &o, const multiset<T> &obj) {
  o << "{";
  for (auto itr = obj.begin(); itr != obj.end(); ++itr)
    o << (itr != obj.begin() ? ", " : "") << *itr;
  o << "}";
  return o;
}
template <class T> ostream &operator<<(ostream &o, const vector<T> &obj) {
  o << "[";
  for (int i = 0; i < (int)obj.size(); ++i)
    o << (i > 0 ? ", " : "") << obj[i];
  o << "]";
  return o;
}
template <class T, class U>
ostream &operator<<(ostream &o, const pair<T, U> &obj) {
  o << "(" << obj.first << ", " << obj.second << ")";
  return o;
}
template <template <class tmp> class T, class U>
ostream &operator<<(ostream &o, const T<U> &obj) {
  o << "{";
  for (auto itr = obj.begin(); itr != obj.end(); ++itr)
    o << (itr != obj.begin() ? ", " : "") << *itr;
  o << "}";
  return o;
}
void print_sim_py(void) { cout << endl; }
template <class Head> void print_sim_py(Head &&head) {
  cout << head;
  print_sim_py();
}
template <class Head, class... Tail>
void print_sim_py(Head &&head, Tail &&...tail) {
  cout << head << " ";
  print_sim_py(forward<Tail>(tail)...);
}

#define print(...) print_sim_py(__VA_ARGS__);
#else
#define print(...) ;
#endif

int main(void) {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  ll n, k;
  ll ans = 0;

  cin >> n >> k;

  vector<ll> l(k), r(k);
  vector<ll> dp(n, 0);

  for (ll i = 0; i < k; i++) {
    cin >> l[i] >> r[i];
  }

  sort(l.begin(), l.end());
  sort(r.begin(), r.end());

  dp[0] = 1;
  for (ll j = 0; j < n; j++) {
    for (ll i = 0; i < k; i++) {
      for (ll x = l[i]; x <= r[i]; x++) {
        if (j + x < n)
          dp[j + x] = (dp[j] + dp[j + x]) % MOD;
      }
    }
  }

  cout << dp[n - 1] << endl;

  return 0;
}

#define _USE_MATH_DEFINES

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using ld = long double;

constexpr ll MOD = 998244353;

#ifndef ONLINE_JUDGE
template <class T, class U>
ostream &operator<<(ostream &o, const map<T, U> &obj) {
  o << "{";
  for (auto &x : obj)
    o << " (" << x.first << " : " << x.second << ")"
      << ",";
  o << " }";
  return o;
}
template <class T> ostream &operator<<(ostream &o, const set<T> &obj) {
  o << "{";
  for (auto itr = obj.begin(); itr != obj.end(); ++itr)
    o << (itr != obj.begin() ? ", " : "") << *itr;
  o << "}";
  return o;
}
template <class T> ostream &operator<<(ostream &o, const multiset<T> &obj) {
  o << "{";
  for (auto itr = obj.begin(); itr != obj.end(); ++itr)
    o << (itr != obj.begin() ? ", " : "") << *itr;
  o << "}";
  return o;
}
template <class T> ostream &operator<<(ostream &o, const vector<T> &obj) {
  o << "[";
  for (int i = 0; i < (int)obj.size(); ++i)
    o << (i > 0 ? ", " : "") << obj[i];
  o << "]";
  return o;
}
template <class T, class U>
ostream &operator<<(ostream &o, const pair<T, U> &obj) {
  o << "(" << obj.first << ", " << obj.second << ")";
  return o;
}
template <template <class tmp> class T, class U>
ostream &operator<<(ostream &o, const T<U> &obj) {
  o << "{";
  for (auto itr = obj.begin(); itr != obj.end(); ++itr)
    o << (itr != obj.begin() ? ", " : "") << *itr;
  o << "}";
  return o;
}
void print_sim_py(void) { cout << endl; }
template <class Head> void print_sim_py(Head &&head) {
  cout << head;
  print_sim_py();
}
template <class Head, class... Tail>
void print_sim_py(Head &&head, Tail &&...tail) {
  cout << head << " ";
  print_sim_py(forward<Tail>(tail)...);
}

#define print(...) print_sim_py(__VA_ARGS__);
#else
#define print(...) ;
#endif

int main(void) {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  ll n, k;
  ll ans = 0;

  cin >> n >> k;

  vector<ll> l(k), r(k);
  vector<ll> dp(n, 0);
  vector<ll> sum(n + 1, 0);

  for (ll i = 0; i < k; i++) {
    cin >> l[i] >> r[i];
  }

  dp[0] = 1;
  sum[1] = 1;
  for (ll j = 2; j < n + 1; j++) {
    for (ll i = 0; i < k; i++) {
      ll li = max(j - l[i], 0ll);
      ll ri = max(j - r[i] - 1, 0ll);
      ll s = sum[li] - sum[ri];
      s = s < 0 ? s + MOD : s;
      dp[j - 1] = (dp[j - 1] + s) % MOD;
    }
    sum[j] = (sum[j - 1] + dp[j - 1]) % MOD;
  }
  print(sum) print(dp)

          cout
      << dp[n - 1] << endl;

  return 0;
}