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)

/*
Dont BLUNDER
*/

// #pragma GCC optimize("O3")
// #pragma comment(linker, "/stack:200000000")
// #pragma GCC optimize("Ofast")
// #pragma GCC optimization ("unroll-loops")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <array>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include<climits>
#include <iomanip>
#include <string>
#include <sstream>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <complex>
#include <cmath>
#include <numeric>
#include <bitset>
#include <functional>
#include <random>
#include <ctime>
#include <chrono>
using namespace std;
/*#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;


 */
//#define d long double
#define int long long
#define pii pair<int,int>
#define pb push_back
#define endl '\n'
#define pi acos(-1)

#define init(x,a) memset(x,a,sizeof(x))
#define all(c) c.begin(),c.end()
int const mod1 = 998244353;
int const mod = 1000000007;
#define bitcount(x)       __builtin_popcountll(x)
#define l first
#define r second
const int inf = LLONG_MAX;
int toint(const string &s) {stringstream ss; ss << s; int x; ss >> x; return x;}
string tostring ( int number ) {stringstream ss; ss << number; return ss.str();}
#define trace1(x)                cerr<<#x<<": "<<x<<endl
#define trace2(x, y)             cerr<<#x<<": "<<x<<" | "<<#y<<": "<<y<<endl
#define trace3(x, y, z)          cerr<<#x<<":" <<x<<" | "<<#y<<": "<<y<<" | "<<#z<<": "<<z<<endl
#define haha ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// * Using PBDS *
/*typedef tree<int, null_type, less<int>, rb_tree_tag,
            tree_order_statistics_node_update>
               os; */

struct cmp
{
	bool operator() (pii a, pii b) {
		return (a.l < b.l);
	}
};

int modexp(int x, int n) {
	if (n == 0) {
		return 1;
	}
	else if (n & 1) {
		return (modexp((x * x) % mod, n / 2) % mod * x % mod) % mod;
	}
	else {
		return (modexp((x * x) % mod, n / 2) % mod);
	}
}

int modinv(int n)
{
	return modexp(n, mod - 2);
}

int gcd(int a, int b) {
	if (b == 0) {
		return a;
	}
	return gcd(b, a % b);
}

int segm_tree[600001];
int a[200001];

void recalculate(int node) {
	//calculate the solution for the current segment,
	//considering the sons are correctly solved
	segm_tree[node] = (segm_tree[2 * node ] + segm_tree[2 * node + 1]) % mod1;
}

void build(int node, int left, int right) { //"node" is the index in the array, while "left"
	// and "right" are the ends of the current segment
	if (left == right) {
		segm_tree[node] = a[left]; //we are in a leaf node
	} else {
		int middle = (left + right) / 2;
		build(2 * node, left, middle);
		build(2 * node + 1, middle + 1, right);
		recalculate(node);
	}
}

void update(int node, int left, int right, int x, int y) {
	if (left == right) { //we are in the xth leaf
		segm_tree[node] = y;
	} else {
		int middle = (left + right) / 2;
		if (x <= middle) { //we need to update the left son
			update(2 * node , left, middle, x, y);
		} else {
			update(2 * node + 1, middle + 1, right, x, y);
		}
		//after updating said son, recalculate the current segment
		recalculate(node);
	}
}

int query(int node, int left, int right, int x, int y) {

	if (y < left or right < x)
	{
		// range represented by a node is completely outside the given range
		return 0;
	}
	if (x <= left && right <= y) {
		//the segment of "node" is completely included in the query
		return segm_tree[node];
	} else {
		//int answer = -10000;
		int middle = (left + right) / 2;
		int p1 = query(2 * node, left, middle, x, y);
		int p2 = query(2 * node + 1, middle + 1, right, x, y);
		//we would not have entered this function if (x, y) and (left, right) had nothing in common,
		//so there is no risk of answer returning -Infinity here, as either the left or the right son
		//would update it
		return (p1 + p2) % mod1;
	}
}





signed main()
{
	haha
#ifndef ONLINE_JUDGE

	freopen("inp.txt", "r", stdin);

	freopen("out1.txt", "w", stdout);
#endif
	vector<pii> v;
	int n, k;
	cin >> n >> k;
	int ans = 0;

	init(a, 0);

	a[1] = 1;
	build(1, 1, n);
	for (int i = 0; i < k; i++) {
		int x; int y;
		cin >> x >> y;
		v.pb({x, y});
	}
	for (int i = 2; i <= n; i++) {
		int temp = 0;
		for (auto x : v) {
			int l = x.first;
			int r = x.second;
			if (i - l >= 1) {
				int qr = i - l;
				int ql = max(1ll, i - r);
				temp += query(1, 1, n, ql, qr);
				temp %= mod1;

			}
		}
		a[i] = temp;
		update(1, 1, n, i, temp);





	}

	cout << a[n];
















}