#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<ll> vll;
typedef vector<vector<ll>> vvll;

#define REP(k, n) for (ll k = 0; k < (ll)(n); ++k)
#define REPREV(k, n) for (ll k = (ll)(n)-1; k >= 0; --k)
#define FOR(k, a, b) for (ll k = (ll)(a); k < (ll)(b); ++k)
#define FORREV(k, a, b) for (ll k = (ll)(b)-1; k >= (ll)(a); --k)
#define FOREACH(e, v) for (auto& e : v)

#define TGET(t, i) get<i>(t)
#define TSET(t, i, a) get<i>(t) = a
// MinHeap - priority_queue<ll, vll, greater<ll>> pq;

#define EVEN(n) ((n)&1) == 0
#define ODD(n) ((n)&1) == 1

#define SORT(v) sort(v.begin(), v.end())
#define SORTREV(v) sort(v.rbegin(), v.rend())
#define SHUFFLE(v) random_shuffle(v.begin(), v.end())
//srand(unsigned(time(0)));

#define REMOVEAT(v, i) v.erase(v.begin() + i)
#define REVERSE(v) reverse(v.begin(), v.end())
#define UNIQUE(v) \
    SORT(v);      \
    v.resize(distance(v.begin(), unique(v.begin(), v.end())))

ostream& operator<<(ostream& str, const pll& p) {
    str << p.first << " " << p.second;
    return str;
}

template <typename T>
void join(T& arr, string sep) {
    bool first = true;
    for (auto t : arr) {
        if (first) {
            first = false;
            cout << t;
        } else {
            cout << sep << t;
        }
    }
    cout << "\n";
}

const ll md = 998244353;
ll MOD(ll x) {
    ll r = x % md;
    if (r < 0) {
        r += md;
    }
    return r;
}

#define POS "POSSIBLE"
#define IMPOS "IMPOSSIBLE"

// #define INF DBL_MAX
// #define INF LLONG_MAX
// #define MINF LLONG_MIN
#define INF 1e18
#define MINF -INF

struct SegmentTree {
    vll tree;
    ll base;

    SegmentTree(vll& a) {
        base = 1;
        ll n = a.size();
        while (base < n) {
            base *= 2;
        }
        tree.resize(2 * base);
        REP(i, n) {
            tree[i + base] = a[i];
        }
        FOR(i, n, base) {
            tree[i + base] = 0;
        }
        FORREV(i, 1, base) {
            tree[i] = tree[2 * i] + tree[2 * i + 1];
        }
    }

    ll query(ll l, ll r) {
        r++;
        ll res = 0;
        for (l += base, r += base; l < r; l /= 2, r /= 2) {
            if (l % 2 == 1)
                res += tree[l++];
            if (r % 2 == 1)
                res += tree[--r];
        }
        return res;
    }

    void update(ll i, ll v) {
        i += base;
        tree[i] = v;
        for (i /= 2; i >= 1; i /= 2) {
            tree[i] = tree[2 * i] + tree[2 * i + 1];
        }
    }
};


void solve() {
    ll n, k;
    cin >> n >> k;
    ll res = 0;
    vector<pll> ranges;
    REP(i, k) {
        ll l, r;
        cin >> l >> r;
        ranges.push_back({l, r});
    }
    SORT(ranges);

    vll a(n);
    a[n - 1] = 1;
    SegmentTree st(a);

    REPREV(i, n - 1) {
        ll cur = 0;
        REP(j, ranges.size()) {
            ll l = ranges[j].first + i;
            ll r = min(n - 1, ranges[j].second + i);
            if (l >= n)
                break;
            ll cnt = st.query(l, r);
            cur = (cur + cnt) % md;
        }
        st.update(i, cur);
    }

    // cout << fixed << setprecision(6);
    cout << st.query(0, 0) << "\n";
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int tt = 1;
    // cin >> tt;
    for (int t = 1; t <= tt; t++) {
        // cout << "Case #" << t << ": ";
        solve();
    }

// #ifdef DEBUG
//     for (int t = 1; t <= tt || cin.rdbuf()->in_avail(); t++) {
//         // cout << "Case #" << t << ": ";
//         solve();
//     }
// #else
//     for (int t = 1; t <= tt; t++) {
//         // cout << "Case #" << t << ": ";
//         solve();
//     }
// #endif

    return 0;
}

Measured memory_bytes: 8992