#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
#define all(x) (x).begin(),(x).end()
using namespace std;
constexpr int INF = 1e9, MOD = 1e9 + 7;
constexpr int64_t LINF = 5e18, LMOD = 998244353;
// #include <atcoder/all>
// using namespace atcoder;
// const int dy[]={0,-1,0,1,1,-1,-1,1};
// const int dx[]={1,0,-1,0,1,1,-1,-1};

/*
・遅延評価セグメント木
    > query, update O(logN)
[引数]
LazySegmentTree<Monoid, OperatorMonoid> seg(sz, f, g, h, d1, d0, v, p);
> sz : 要素数
>  f : 要素と要素をマージする関数
>  g : 要素に作用素を作用させる関数
>  h : 作用素と作用素をマージする関数
> d1 : 要素のモノイド
> d0 : 作用素のモノイド
>  v : 初期化用の配列
>  p : 区間に対する操作が要素数に比例して変化する場合 ( p(a, b) = g(a, a, ..., a) [aはb個] )
[備考]
以下の3つの条件を満たすときに使える
1. g(f(a, b), c) = f(g(a, c), g(b, c))
( 1'. g(f(a, b), p(c, d)) = f(g(a, p(c, d / 2)), g(b, p(c, d / 2))) )
2. g(g(a, b), c) = g(a, h(b, c))
3. g(a, d0) = a
[典型例]
> 区間加算 -> 区間和
LazySegmentTree<ll> seg(N, plus<ll>(), plus<ll>(), plus<ll>(), 0, 0, vl(N,0), multiplies<ll>());
> 区間加算 -> 区間最小
LazySegmentTree<ll> seg(N, [](ll a,ll b){return min(a,b);}, plus<ll>(), plus<ll>(), INFF, 0);
> 区間更新 -> 区間和
LazySegmentTree<ll> seg(N, plus<ll>(), [](ll a,ll b){return b;}, [](ll a,ll b){return b;}, 0, INFF, vl(N,0), multiplies<ll>());
> 区間更新 -> 区間最小
LazySegmentTree<ll> seg(N, [](ll a,ll b){return min(a,b);}, [](ll a,ll b){return b;}, [](ll a,ll b){return b;}, INFF, INFF);
[使用例]
seg.update(l, r, x);        // 半開区間[l, r)に作用素xを作用
seg.query(l, r);            // 半開区間[l, r)に対する演算の結果
seg[k];                     // k番目の要素を取得
*/

template <typename Monoid, typename OperatorMonoid = Monoid> struct LazySegmentTree {

  typedef function< Monoid(Monoid, Monoid) > F;
  typedef function< Monoid(Monoid, OperatorMonoid) > G;
  typedef function< OperatorMonoid(OperatorMonoid, OperatorMonoid) > H;
  typedef function< OperatorMonoid(OperatorMonoid, int) > P;

  int sz;
  F f;
  G g;
  H h;
  P p;
  Monoid d1;
  OperatorMonoid d0;
  vector< Monoid > dat;
  vector< OperatorMonoid > laz;

  LazySegmentTree(int n, F f, G g, H h, Monoid d1, OperatorMonoid d0,
              vector< Monoid > v = vector< Monoid >(), P p = [] (OperatorMonoid a, int b) { return a; })
              : f(f), g(g), h(h), d1(d1), d0(d0), p(p) {
    sz = 1; while (sz < n) sz <<= 1;
    dat.assign(2 * sz - 1, d1);
    laz.assign(2 * sz - 1, d0);
    if (n == (int)v.size()) build(n, v);
  }

  void build(int n, vector<Monoid> &v) {
    for (int i = 0; i < n; i++)
      dat[i + sz - 1] = v[i];
    for (int i = sz - 2; i >= 0; i--)
      dat[i] = f(dat[i * 2 + 1], dat[i * 2 + 2]);
  }

  inline void eval(int len, int k) {
    if (laz[k] == d0) return;
    if (k * 2 + 1 < sz * 2 - 1) {
      laz[k * 2 + 1] = h(laz[k * 2 + 1], laz[k]);
      laz[k * 2 + 2] = h(laz[k * 2 + 2], laz[k]);
    }
    dat[k] = g(dat[k], p(laz[k], len));
    laz[k] = d0;
  }

  Monoid update(int a, int b, OperatorMonoid x, int k, int l, int r) {
    eval(r - l, k);
    if(r <= a || b <= l) return dat[k];
    if(a <= l && r <= b) {
      laz[k] = h(laz[k], x);
      return g(dat[k], p(laz[k], r - l));
    }
    return dat[k] = f(update(a, b, x, k * 2 + 1, l, (l + r) / 2),
            update(a, b, x, k * 2 + 2, (l + r) / 2, r));
  }

  Monoid update(int a, int b, OperatorMonoid x) {
    return update(a, b, x, 0, 0, sz);
  }

  Monoid query(int a, int b, int k, int l, int r) {
    eval(r - l, k);
    if (r <= a || b <= l) return d1;
    if (a <= l && r <= b) return dat[k];
    Monoid vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
    Monoid vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
    return f(vl, vr);
  }

  Monoid query(int a, int b) {
    return query(a, b, 0, 0, sz);
  }

  Monoid operator[](const int &k) {
    return query(k, k + 1);
  }

};

using fint64 = int_fast64_t;
template<fint64 MOD>
struct ModInt {
	fint64 x;
	ModInt():x(0){}
	ModInt(fint64 x):
		x(x>=0?x%MOD:(MOD-(-x)%MOD)%MOD)
		{}
	// 負号
	ModInt operator -() const{
		return ModInt(-x);
	}
	// 加算
	ModInt &operator +=(const ModInt &rhs){
		x+=rhs.x;
		if(x>=MOD) x-=MOD;
		return (*this);
	}
	ModInt operator +(const ModInt &rhs) const{
		return ModInt(*this)+=rhs;
	}
	// 減算
	ModInt &operator -=(const ModInt &rhs){
		x+=MOD-rhs.x;
		if(x>=MOD) x-=MOD;
		return (*this);
	}
	ModInt operator -(const ModInt &rhs) const{
		return ModInt(*this)-=rhs;
	}
	// 乗算
	ModInt &operator *=(const ModInt &rhs){
		x*=rhs.x;
		if(x>=MOD) x%=MOD;
		return (*this);
	}
	ModInt operator *(const ModInt &rhs) const{
		return ModInt(*this)*=rhs;
	}
	// 除算
	ModInt &operator /=(const ModInt &rhs){
		(*this)*=rhs.inverse();
		return (*this);
	}
	ModInt operator /(const ModInt &rhs) const{
		return ModInt(*this)/=rhs;
	}
	// 等号
	bool operator ==(const ModInt &rhs){
		return x==rhs.x;
	}
	bool operator !=(const ModInt &rhs){
		return x!=rhs.x;
	}
	// 累乗
	ModInt pow(fint64 n) const{
		fint64 tmp=x;
		fint64 ret=1;
		while(n>0){
			if(n&1) ret=ret*tmp%MOD;
			tmp=tmp*tmp%MOD;
			n>>=1ll;
		}
		return ModInt(ret);
	}
	// 逆元
	ModInt inverse() const{
		fint64 a=x,b=MOD,s=1,t=0;
		while(b>0){
			fint64 u=a/b;
			a-=u*b;
			s-=u*t;
			swap(a,b);
			swap(s,t);
		}
		return ModInt(s);
	}
	// 入出力
	friend istream &operator >>(istream &lhs,ModInt<MOD> &rhs){
		fint64 x; lhs>>x;
		rhs=ModInt<MOD>(x);
		return lhs;
	}
	friend ostream &operator <<(ostream &lhs,const ModInt<MOD> &rhs){
		return lhs<<rhs.x;
	}
};

using mint = ModInt<LMOD>;
int main() {
	int n, k; cin >> n >> k;
	int l[k], r[k];
	for(int i = 0; i < k; ++i) cin >> l[i] >> r[i];
	LazySegmentTree<mint> seg(n, [](mint a, mint b){return a + b;}, [](mint a, mint b){return a + b;}, [](mint a, mint b){return a + b;}, 0, 0);
	seg.update(0, 1, 1);
	for(int i = 0; i < n; ++i) {
		for(int j = 0; j < k; ++j) {
			seg.update(min(n, i + l[j]), min(n, i + r[j] + 1), seg[i]);
		}
	}
	cout << seg[n - 1] << '\n';
	return 0;
}


Measured memory_bytes: 11400