// Best practice
 
#include<bits/stdc++.h>
 
#define int         long long
#define pb          push_back
#define pf          emplace_front
#define all(a)      (a).begin(),(a).end()
#define rall(a)     (a).rbegin(),(a).rend()
#define pii 		pair<int,int>
#define psi 		pair<string,int>
#define vi 			vector<int>
#define vpii  		vector<pii>
#define vvi 		vector<vi>
#define sz(x)	    (int)(x).size()
#define x           first
#define y           second
#define endl        '\n'
#define tezz        ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define MOD         1000000007
#define hell        998244353
#define prec(n) 	fixed<<setprecision(n)
#define ini(a, i) 	memset(a, i, sizeof(a))
#define output(x)   cout << (x ? "YES" : "NO")<<endl;
using namespace std;
 
#define debug(vec) cout<<(#vec)<<" : [ "; for (auto& i: vec) cout<<i<<" "; cout<< "]" << endl
#define debugp(vec) cout<<(#vec)<<" : [ "; for (auto& i: vec) cout<<"("<<i.x<<","<<i.y<<")"<<" "; cout<< "]" << endl
#define trace(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args);cout << endl; }
void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
    cout << "[" << *it << ": " << a << "]\t";
    err(++it, args...);
}
 
// const int dx[4] = { -1, 1, 0, 0};
// const int dy[4] = {0, 0, -1, 1};
// int dX[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
// int dY[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
 
 
// Code from Here -------------------------------------------------------------------------------

struct Lazy
{
    int N;
    vector<int> st, pending;
    void init(int n) {
        N = 2e5 + 5;
        st = vector<int> (4 * N, 0);
        pending = vector<int> (4 * N, 0);
        // build(a, 1, 0, n - 1);
    }
    void build(vector<int> a, int v, int tl, int tr) {
        if (tl == tr)st[v] = a[tl];
        else {
            int mid = (tl + tr) / 2;
            build(a, 2 * v, tl, mid);
            build(a, 2 * v + 1, mid + 1, tr);
            st[v] = (st[2 * v] + st[2 * v + 1])%hell;
        }
    }
    void push(int v) {
        if (!pending[v])return;
        st[2 * v] += pending[v];
        st[2 * v + 1] += pending[v];
        pending[2 * v] += pending[v];
        pending[2 * v + 1] += pending[v];
        pending[v] = 0;
    }
    void update(int v, int tl, int tr, int l, int r, int add) {
        // [l,r]
        if (l > r)return;
        if (tl == l && tr == r) {
            (st[v] += add)%=hell;
            (pending[v] += add)%=hell;
        }
        else {
            push(v);
            int mid = (tl + tr) / 2;
            update(2 * v, tl, mid, l, min(r, mid), add);
            update(2 * v + 1, mid + 1, tr,  max(l, mid + 1), r, add);
            st[v] = (st[2 * v] + st[2 * v + 1])%hell;
        }
    }
    int getMin(int v, int tl, int tr, int l, int r) {
        // [l,r]
        if (l > r)return 0;
        if (tl == l && tr == r) {
            return st[v];
        }
        else {
            push(v);
            int mid = (tl + tr) / 2;
            int resl = getMin(2 * v, tl, mid, l, min(r, mid));
            int resr = getMin(2 * v + 1, mid + 1, tr, max(l, mid + 1), r);
            return (resl + resr)%hell;
        }
    }
};

signed main() {
	tezz
 
	#ifndef ONLINE_JUDGE
		freopen("input.txt", "r", stdin);
		freopen("output.txt", "w", stdout);
	#endif
 
	int n, k, p, q;
	cin >> n >> k;
	Lazy tree;
	tree.init(n+1);
	vpii arr;
	for(int i=0; i<k; i++){
		cin >> p >> q;		
		arr.pb({p, q});
	}
	// debugp(arr);
	tree.update(1, 0, n-1, 0, 0, 1);
	for(int i=0; i<n; i++){
		int x = tree.getMin(1, 0, n-1, i, i);
		// trace(i, x);
		for(auto it: arr){
			if(i+it.x >= n)continue;
			tree.update(1, 0, n-1, i+it.x, min(n-1, i+it.y), x);
		}
	}
	cout << tree.getMin(1, 0, n-1, n-1, n-1) << endl;
 
	return 0;
}  

Measured memory_bytes: 15852