Problem:
Score : 400 points

Problem Statement

There are N cells arranged in a row, numbered 1, 2, \ldots, N from left to right.

Tak lives in these cells and is currently on Cell 1. He is trying to reach Cell N by using the procedure described below.

You are given an integer K that is less than or equal to 10, and K non-intersecting segments [L_1, R_1], [L_2, R_2], \ldots, [L_K, R_K].
Let S be the union of these K segments.
Here, the segment [l, r] denotes the set consisting of all integers i that satisfy l \leq i \leq r.

When you are on Cell i, pick an integer d from S and move to Cell i + d. You cannot move out of the cells.

To help Tak, find the number of ways to go to Cell N, modulo 998244353.

Constraints

2 \leq N \leq 2 \times 10^5

1 \leq K \leq \min(N, 10)

1 \leq L_i \leq R_i \leq N

[L_i, R_i] and [L_j, R_j] do not intersect (i \neq j)

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N K
L_1 R_1
L_2 R_2
:
L_K R_K

Output

Print the number of ways for Tak to go from Cell 1 to Cell N, modulo 998244353.

Sample Input 1

5 2
1 1
3 4

Sample Output 1

4

The set S is the union of the segment [1, 1] and the segment [3, 4], therefore S = \{ 1, 3, 4 \} holds.

There are 4 possible ways to get to Cell 5:

1 \to 2 \to 3 \to 4 \to 5,

1 \to 2 \to 5,

1 \to 4 \to 5 and

1 \to 5.

Sample Input 2

5 2
3 3
5 5

Sample Output 2

0

Because S = \{ 3, 5 \} holds, you cannot reach to Cell 5.
Print 0.

Sample Input 3

5 1
1 2

Sample Output 3

5

Sample Input 4

60 3
5 8
1 3
10 15

Sample Output 4

221823067

Note that you have to print the answer modulo 998244353.

Solution in C++ (GCC 9.2.1) (judge verdict: Accepted)

#include<iostream>
#include<string>
#include<vector>
#include<utility>
#include<algorithm>
#include<map>
#include<set>
#include<cstdlib>
#include<cmath>
#include<numeric>
#include<iomanip>
#include<functional>
#include<cstdlib>
#include<queue>
#include<deque>
#include <iterator>     // std::back_inserter
const double PI = acos(-1);
using namespace std;
using ll =long long;
#define rep(i,n)for(ll i=0;i<(n);i++)
const int mod = 998244353;
const ll inf = 1e18 + 1;
int ctoi(char c) {
	if (c >= '0' && c <= '9') {
		return c - '0';
	}
	return 0;
}

ll gcd(ll a, ll b) {
	if (a % b == 0) {
		return b;
	}
	else {
		return gcd(b, a % b);
	}
}
ll lcm(ll a, ll b) {
	return a * b / gcd(a, b);
};
//fixed << setprecision(2)
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;
}

/*コンビネーション*/

//ll f[101010], rf[101010];
//ll inv(ll x) {
//	ll res = 1;
//	ll k = mod - 2;
//	ll y = x;
//	while (k) {
//		if (k & 1) res = (res * y) % mod;
//		y = (y * y) % mod;
//		k /= 2;
//	}
//	return res;
//}
//void init() {
//	f[0] = 1;
//	for (ll i = 1; i < 101010;i++) f[i] = (f[i - 1] * i) % mod;
//	for(ll i = 0; i < 101010; i++) rf[i] = inv(f[i]);
//}
////---------------------------------------------------------------------------------------------------
//ll C(int n, int k) {
//	ll a = f[n]; // = n!
//	ll b = rf[n - k]; // = (n-k)!
//	ll c = rf[k]; // = k!
//
//	ll bc = (b * c) % mod;
//
//	return (a * bc) % mod;
//}

///*コンビネーション*/
//
///*Union Find*/
//#define MAX_N 200000
//#define MAX_M 200000
//vector<ll>par(MAX_N);
//vector<ll>ran(MAX_N);
//void init(ll N) {
//	rep(i, N) {
//		par[i] = i;
//		ran[i] = 0;
//	}
//}
//ll find(ll x) {
//	if (par[x] == x) {
//		return x;
//	}
//	else {
//		return par[x] = find(par[x]);
//	}
//}
////xとyの属する集合を併合
//void unite(ll x,ll y) {
//	x = find(x);
//	y = find(y);
//	if (x == y)return;
//	if (ran[x] < ran[y]) {
//		par[x] = y;
//
//	}
//	else {
//		par[y] = x;
//		if (ran[x] == ran[y])ran[x]++;
//	}
//}
//bool same(ll x, ll y) {
//	return find(x) == find(y);
//}
///*Union Find*/
//小文字=大文字+32
//struct edge {
//	vector<int>to;
//	ll cost;
//	int p;
//	ll w;
//	int col;
//};
//	int N;
//	cin >> N;
//	vector<pair<int, pair<int,ll>>>Q(N-1);
//	vector<ll> w(N - 1);
//	rep(i, N-1){
//		cin >> Q[i].first>>Q[i].second.first>>Q[i].second.second;
//	}
//	sort(Q.begin(), Q.end());
//	vector<edge>G(N);
//	rep(i, N - 1) {
//		G[Q[i].first-1].to.push_back(Q[i].second.first-1);
//		G[Q[i].second.first-1].to.push_back(Q[i].first-1);
//		G[Q[i].second.first - 1].p = Q[i].first-1;
//		G[Q[i].second.first-1].w = Q[i].second.second;
//	}
//	G[0].cost = 0;
//	G[0].p = -1;
//	G[0].w = 0;
//	queue<int>Qu;
//	vector<bool> A(N,true);
//	for (int i = 0; i < G[0].to.size(); i++) {
//		Qu.push(G[0].to[i]);
//		A[G[0].to[i]] = false;
//	}
//	int v;
//	while (!Qu.empty()) {
//		v = Qu.front();
//		Qu.pop();
//		G[v].cost = G[G[v].p].cost + G[v].w;
//		for (int i = 0; i < G[v].to.size(); i++) {
//			if (A[G[v].to[i]]) {
//				Qu.push(G[v].to[i]);
//				A[G[v].to[i]] = false;
//			}
//		}
//	}
//	G[0].col = 0;
//	vector<bool>B(N, true);
//	for (int i = 0; i < G[0].to.size(); i++) {
//		Qu.push(G[0].to[i]);
//			cout << G[0].to[i]<<endl;
//			B[G[0].to[i]] = false;
//	}
//	while (!Qu.empty()) {
//		v = Qu.front();
//		Qu.pop();
//		if (labs(G[v].cost-G[G[v].p].cost) % 2 == 0) {
//			if (G[G[v].p].col == 0) {
//				G[v].col = 0;
//			}
//			else {
//				G[v].col = 1;
//			}
//		}
//		else {
//			if (G[G[v].p].col == 0) {
//				G[v].col = 1;
//			}
//			else {
//				G[v].col = 0;
//			}
//		}
//		for (int i = 0; i < G[v].to.size(); i++) {
//			if (B[G[v].to[i]]) {
//				Qu.push(G[v].to[i]);
//				B[G[v].to[i]] = false;
//			}
//		}
//	}
//	rep(i, N) {
//		//cout << G[i].col << endl;
//	}
//
//}
int main() {
	ll N,K;
	cin >> N >> K;
	vector<ll>L(K),R(K);
	rep(i, K) {
		cin >> L[i] >> R[i];
	}
	vector<ll>dp(N+1,0);
	vector<ll>a(N + 1, 0);
	a[1] = 1;
	dp[1] = 1;
	for(ll i=2;i<=N;i++) {
		rep(j, K) {
			if (i >= L[j]) {
				ll r = i - R[j] - 1;
				dp[i] += a[i - L[j]] - a[max(r, (ll)0)];
				dp[i] %= mod;
			}
		}
		a[i] = a[i - 1] + dp[i];
		
	}
	cout << dp[N];


}