#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL_
void debug_out() {cerr << endl;}
template<typename Head,typename... Tail> void debug_out(Head H,Tail... T){cerr << ' ' << H; debug_out(T...);}
#define debug(...) cerr << 'L' << __LINE__ << " [" << #__VA_ARGS__ << "]:",debug_out(__VA_ARGS__)
#define dump(x) cerr << 'L' << __LINE__ << " " << #x << " = " << (x) << endl;
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
#define rep(i,n) for (int i = 0; i < (int)(n); i ++)
#define irep(i,n) for (int i = (int)(n) - 1;i >= 0;--i)
using ll = long long;
using PL = pair<ll,ll>;
using P = pair<int,int>;
constexpr int INF = 1000000000;
constexpr long long HINF = 1000000000000000;
constexpr long long MOD = 1000000007;// = 998244353;
constexpr double EPS = 1e-4;
constexpr double PI = 3.14159265358979;


template<int Modulus> 
struct ModInt {
    long long x;
    ModInt(long long x = 0) :x((x%Modulus + Modulus)%Modulus) {}
    constexpr ModInt &operator+=(const ModInt a) {if ((x += a.x) >= Modulus) x -= Modulus; return *this;}
    constexpr ModInt &operator-=(const ModInt a) {if ((x += Modulus - a.x) >= Modulus) x -= Modulus; return *this;}
    constexpr ModInt &operator*=(const ModInt a) {(x *= a.x) %= Modulus; return *this;}
    constexpr ModInt &operator/=(const ModInt a) {return *this *= a.inverse();}

    constexpr ModInt operator+(const ModInt a) const {return ModInt(*this) += a.x;}
    constexpr ModInt operator-(const ModInt a) const {return ModInt(*this) -= a.x;}
    constexpr ModInt operator*(const ModInt a) const {return ModInt(*this) *= a.x;}
    constexpr ModInt operator/(const ModInt a) const {return ModInt(*this) /= a.x;}
    
    friend constexpr ostream& operator<<(ostream& os,const ModInt<Modulus>& a) {return os << a.x;}
    friend constexpr istream& operator>>(istream& is,ModInt<Modulus>& a) {return is >> a.x;}
    
    ModInt inverse() const {// x ^ (-1) 
        long long a = x,b = Modulus,p = 1,q = 0;
        while (b) {long long d = a/b; a -= d*b; swap(a,b); p -= d*q; swap(p,q);}
        return ModInt(p);
    }
    ModInt pow(long long N) {// x ^ N 
        ModInt a = 1;
        while (N) {
            if (N&1) a *= *this;
            *this *= *this;
            N >>= 1;
        }
        return a;
    }
};

using mint = ModInt<998244353>;

//https://yukicoder.me/submissions/470340
template <class Monoid1,class Monoid2> struct LazySegmentTree {
    int N;
    vector<Monoid1> tree;
    vector<Monoid2> lazy;

    //depending on the problem
    Monoid1 unit_x;
    Monoid2 unit_m;
    using FX = function<Monoid1(Monoid1,Monoid1)>; FX fx;
    using FA = function<Monoid1(Monoid1,Monoid2)>; FA fa;
    using FM = function<Monoid2(Monoid2,Monoid2)>; FM fm;
    //

    LazySegmentTree(int _N,Monoid1 _unitx,Monoid2 _unitm,FX _fx,FA _fa,FM _fm):
        N(_N),unit_x(_unitx),unit_m(_unitm),fx(_fx),fa(_fa),fm(_fm) {
        tree.assign(2*N,unit_x);
        lazy.assign(2*N,unit_m);
    }

    void build(vector<Monoid1> &array) {
        for (int i = N; i < 2*N; i++) tree[i] = array[i - N];
        for (int i = N - 1; i > 0; i--) tree[i] = fx(tree[i << 1],tree[i << 1|1]);
    }

    Monoid1 eval_at(int i) {
        return fa(tree[i],lazy[i]);
    }

    void propagate_at(int i) {
        tree[i] = eval_at(i);
        lazy[i << 1] = fm(lazy[i << 1],lazy[i]);
        lazy[i << 1|1] = fm(lazy[i << 1|1],lazy[i]);
        lazy[i] = unit_m;
    }

    void propagate_above(int i) {
        int H = 0;
        while ((1<<H) < i) ++H;
        for (int h = H - 1;h > 0;--h) {
            propagate_at(i >> h);
        }
    }

    void recalc_above(int i) {
        while (i > 1) {
            i >>= 1;
            tree[i] = fx(eval_at(i << 1),eval_at(i << 1|1));
        }
    }

    void set_val(int i,Monoid1 x) {
        i += N;
        propagate_above(i);
        tree[i] = x;
        lazy[i] = unit_m;
        recalc_above(i);
    }

    Monoid1 fold(int L,int R) {
        L += N; R += N;
        propagate_above(L/(L & -L));
        propagate_above(R/(R & -R) - 1);
        Monoid1 vL = unit_x,vR = unit_x;
        while (L < R) {
            if (L&1) {vL = fx(vL,eval_at(L)); ++L;}
            if (R&1) {--R; vR = fx(eval_at(R),vR);}
            L >>= 1; R >>= 1;
        }
        return fx(vL,vR);
    }

    void operate_range(int L,int R,Monoid2 x) {
        L += N; R += N;
        int L0 = L/(L & -L),R0 = R/(R & -R) - 1;
        propagate_above(L0); propagate_above(R0);
        while (L < R) {
            if (L&1) {lazy[L] = fm(lazy[L],x); ++L;}
            if (R&1) {--R; lazy[R] = fm(lazy[R],x);}
            L >>= 1; R >>= 1;
        }
        recalc_above(L0); recalc_above(R0);
    }
    
    /*
    void debug() {
        for (int i = 0;i < 2*N;++i) {printf(" st[%d] : ",i); cout << tree[i];}
        cout << '\n';
        for (int i = 0;i < 2*N;++i) {printf(" lazy[%d] : ",i); cout << lazy[i];}
        cout << '\n';
    }
    */
};

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

    int N,K; cin >> N >> K;
    vector<int> L(K),R(K);
    rep(i,K) cin >> L[i] >> R[i];

    LazySegmentTree<mint,mint> dp(N,0,0,
    [](mint a,mint b){return a + b;},
    [](mint a,mint b){return a + b;},
    [](mint a,mint b){return a + b;}
    );
    dp.set_val(0,1);
    rep(i,N) {
        mint m = dp.fold(i,i + 1);
        rep(j,K) {
            int l = i + L[j];
            int r = min(i + R[j] + 1,N);
            if (l < N) dp.operate_range(l,r,m);
        }
    }
    cout << dp.fold(N - 1,N) << '\n';
    return 0;
}

Measured memory_bytes: 9536