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)

// بساملہ ہیر رحمن نیر رحیم
//---------------------------//
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization ("unroll-loops")
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<cmath>
#include<unordered_map>
#include<unordered_set>
#include<map>
#include<bitset>
#include<cstring>
#include<stack>
#include<queue>
#include<set>
#include<chrono>
#include<list>
#include<climits>
#include<iomanip>
// #include<ext/pb_ds/assoc_container.hpp>
// #include<ext/pb_ds/tree_policy.hpp>
// #define PBDS tree<long long int,null_type,less<long long int>, rb_tree_tag,tree_order_statistics_node_update>
// using namespace __gnu_pbds;
#define arrsize 2000001
#define dpsize 1001
#define vpp vector<PP>
#define vll vector<ll>
#define vcc vector<char>
#define endl "\n"
#define vbb vector<bool>
#define w(t) while(t--)
#define PP pair<ll,ll>
#define test(x) ll t; cin>>t; w(t) x()
#define __lb lower_bound
#define __ub upper_bound
#define szs(x) x.length()
#define szv(x) x.size()
#define INF 1999999996000000010
#define ll long long int
#define takeINP(arr,n) for(long long int i=0;i<n;i++) cin>>arr[i];
#define f(i,s,e) for(long long int i=s;i<e;i++)
#define cf(i,s,e) for(long long int i=s;i<=e;i++)
#define rf(i,e,s) for(long long int i=e-1;i>=s;i--)
#define mem(arr) memset(arr,0,sizeof(arr));
#define MOD 998244353
#define rsz(x,n) x.resize(n)
#define rsr(x,n) x.reserve(n) 
#define mp(a,b) make_pair(a,b)
#define pb push_back
#define print(arr,s,e) f(i,s,e) cout<<arr[i]<<" "; cout<<endl;
#define all(v) v.begin(),v.end()
#define ff first
#define ss second
#define vll vector<ll>
#define triplet pair<ll,pair<ll,ll> >
#define MITR(a,b) map<a,b>::reverse_iterator 
using namespace std;
using namespace chrono;

///---------------Functions---------------------///
ll advceil(ll num,ll den){return (num%den==0?num/den:num/den+1);}
ll lstbt(ll val){ ll msk = val&(val-1); return log2(val^msk);}
ll modexpo(ll a,ll b){	ll res=1;	while(b>0){		if(b&1) res = (res%MOD*a%MOD)%MOD;		a = (a%MOD*a%MOD);		b/=2;	}	return res;}
ll expo(ll a,ll b){	ll res=1;	while(b>0){		if(b&1) res = (res*a);		a = (a*a);		b/=2;	}	return res;}
ll gcd(ll a,ll b){ return a==0?b:gcd(b%a,a); }
vll CALCfactor(ll n){	vll factor(n+2,0);	for(ll i=4;i<=n;i+=2) factor[i]=2;	for(ll j=3;j<=n;j+=2){		if(factor[j]) continue;		for(ll i=2*j;i<=n;i+=j) factor[i]=j;	}	return factor;}
vll CALCprimeNUM(ll n){	vll factor = CALCfactor(n);	vll primeNUM; primeNUM.reserve(n+2);	cf(i,2,n) if(!factor[i]) primeNUM.pb(i);	return primeNUM;}
vll CALCprimeFACTOR(ll n){	vll factor = CALCfactor(n);	vll ans;	while(factor[n]!=0){		ans.pb(factor[n]);		n/=factor[n];	}	ans.pb(n);	return ans;}
vll unique(vll x){	sort(all(x)); set<ll> s;	vll ans; ans.reserve(szv(x));	for(auto elem : x) s.insert(elem);	for(auto elem : s) ans.pb(elem);	return ans;}
vll ZALGO(string s,string pat){	ll lens = szs(pat);	pat+=char(36);	pat+=s;	s = pat;	vll pref(szs(s)+1,0);	pref[0]=szs(s);	ll spt = -1; ll ept = -1; ll processCnt = 0;	for(ll i=1;i<szs(s);i++){		bool isdone = false;		if(i<=ept and i>=spt){			if(pref[i-spt]+i<=ept) pref[i]=pref[i-spt],isdone=true;			processCnt++;		}		if(!isdone){			ll ptr = i; ll lo = 0; 			while(s[lo]==s[ptr]) ptr++,lo++,processCnt++;			if(ept<ptr-1){				spt = i;				ept = ptr-1;			} 			pref[i] = lo; 		}	}	vll ans; ans.reserve(szs(s)-lens);	for(ll i=lens+1;i<szs(s);i++) ans.pb(pref[i]);	return ans;}
void spclSort(vector<pair<pair<ll,ll>,ll>> &v){	ll n = szv(v);	{		vll cnt(n);		for(auto elem : v){			cnt[elem.ff.ss]++;		}		vector<pair<pair<ll,ll>,ll>> a_new(n);		vll pos(szv(cnt));		pos[0]=0;		for(ll i=1;i<szv(cnt);i++){			pos[i]=cnt[i-1]+pos[i-1];		}		for(auto elem : v){			a_new[pos[elem.ff.ss]]=elem;			pos[elem.ff.ss]++;		}		v = a_new;	}	{		vll cnt(n,0);		for(auto elem : v){			cnt[elem.ff.ff]++;		}		vector<pair<pair<ll,ll>,ll>> a_new(n);		vll pos(szv(cnt));		pos[0]=0;		for(ll i=1;i<szv(cnt);i++){			pos[i]=cnt[i-1]+pos[i-1];		}		for(auto elem : v){			a_new[pos[elem.ff.ff]]=elem;			pos[elem.ff.ff]++;		}		v = a_new;	}}
pair<vector<vll>,vector<vll>> getOrdering(string s){	s+=char(36);	vector<vll> dp;  dp.reserve(log2(szs(s))+3);	vector<vll> dp2;  dp2.reserve(log2(szs(s))+3);	vll ordering(szs(s)),eqClass(szs(s));	{		vector<pair<char,ll> > temp(szs(s));		f(i,0,szs(s)) temp[i]={s[i],i};		sort(all(temp));		f(i,0,szv(temp)) ordering[temp[i].ss]=i;		eqClass[temp[0].ss]=0;		f(i,1,szv(temp)){			 if(temp[i].ff!=temp[i-1].ff) eqClass[temp[i].ss]=eqClass[temp[i-1].ss]+1;			 else eqClass[temp[i].ss]=eqClass[temp[i-1].ss];		} 		dp.pb(ordering); dp2.pb(eqClass);	}	ll k=1;	while((1<<(k-1))<szs(s)){		vector<pair<pair<ll,ll>,ll> > arr(szs(s));		for(ll i=0;i<szs(s);i++){			arr[i]={{eqClass[i],eqClass[(i+(1<<(k-1)))%szs(s)]},i};		}		spclSort(arr);		f(i,0,szs(s)) ordering[arr[i].ss]=i;		eqClass[arr[0].ss]=0;		f(i,1,szv(s)){			 if(arr[i].ff!=arr[i-1].ff) eqClass[arr[i].ss]=eqClass[arr[i-1].ss]+1;			 else eqClass[arr[i].ss]=eqClass[arr[i-1].ss];		} 		dp.pb(ordering); dp2.pb(eqClass);		k++;	}	return {dp,dp2};}
vll sortOrdering(vector<vll> dp){	vll arr = dp[szv(dp)-1];	vll ans(szv(arr)); ll cnt = 0;	for(auto elem : arr){		ans[elem]=cnt;		cnt++;	}	return ans;}
vll getLps(string pat){	ll i = 1; ll j = 0;	vll lps(szs(pat),0);	lps[0]=0;	while(i<szs(pat)){		if(pat[i]==pat[j]) lps[i]=j+1,i++,j++;		else if(j==0) lps[i]=0,i++;		else j=lps[j-1];	}	return lps;}
///---------x------------x----------x-----------///
ll BIT[arrsize]={};
ll n;
void update(ll idx,ll val){
	for(ll i=idx;i<=n;i+=(i&(-i))) BIT[i]+=val,BIT[i]%=MOD;
}
ll query(ll idx){
	ll sum = 0;
	for(ll i=idx;i>0;i-=(i&(-i))) sum+=BIT[i],sum%=MOD;
	return sum;
}
ll get(ll l,ll r){
	if(l>r or l<1 or r>n) return 0;
	return (query(r)-query(l-1)+MOD)%MOD;
}

void solve(){
	ll k; cin>>n>>k;
	vpp arr(k);
	f(i,0,k) cin>>arr[i].ff>>arr[i].ss;

	update(1,1);
	cf(i,2,n){
		ll cnt = 0;
		f(j,0,k){
			ll lo = i-arr[j].ff; ll hi = i-arr[j].ss;
			if(lo<1) continue;
			if(hi<1) hi = i-min(arr[j].ss,i-1);
			cnt+=(get(hi,lo));
			cnt%=MOD;
		}
		update(i,cnt);
		// cout<<"#"<<i<<" "<<cnt<<endl;
	}

	cout<<get(n,n)<<endl;
}

int main(){
	#ifndef ONLINE_JUDGE
		freopen("input.txt", "r" ,stdin);
		freopen("output.txt", "w" ,stdout);
	#endif
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    auto start1 = high_resolution_clock::now();
    solve();
    //test(solve);
    auto stop1 = high_resolution_clock::now();
	auto duration = duration_cast<microseconds>(stop1 - start1);
    #ifndef ONLINE_JUDGE
		cerr << "Time: " << duration.count() / 1000.0 << endl;
	    cout<<duration.count()/1000.0<<endl;
    #endif
}