#[allow(unused_imports)]
use {
    itertools::Itertools,
    proconio::{fastout, input, marker::*},
    std::cmp::*,
    std::collections::*,
    std::io::Write,
    std::ops::*,
};

#[allow(unused_macros)]
macro_rules! dbg { ($($e:expr),*) => { #[cfg(debug_assertions)] $({ let (e, mut err) = (stringify!($e), std::io::stderr()); writeln!(err, "{} = {:?}", e, $e).unwrap() })* }; }

#[fastout]
fn main() {
    input! {
        n: usize,
        k: usize,
        mut lr: [(usize, usize); k],
    }
    lr.sort();
    let mut fen = FenwickTree::new(n, Mint(0));
    fen.add(0, Mint(1));
    for i in 1..n {
        for &(l, r) in lr.iter() {
            if i < l {
                break;
            }
            let s = if r <= i {
                fen.sum(i - r..=i - l)
            } else {
                fen.sum(..=i - l)
            };
            // dbg!(i, s);
            fen.add(i, s);
        }
    }
    let ans = fen.sum(n - 1..n);
    println!("{}", ans);
}

struct FenwickTree<T> {
    n: usize,
    tree: Vec<T>,
    e: T,
}
#[allow(dead_code)]
impl<T: std::ops::AddAssign + Clone> FenwickTree<T> {
    fn new(n: usize, e: T) -> Self {
        FenwickTree {
            n,
            tree: vec![e.clone(); n],
            e,
        }
    }
    /// A[i] += w
    fn add<U: Clone>(&mut self, mut idx: usize, w: U)
    where
        T: std::ops::AddAssign<U>,
    {
        idx += 1;
        while idx <= self.n {
            self.tree[idx - 1] += w.clone();
            idx += idx & idx.wrapping_neg();
        }
    }
    /// return A[0] + ... + A[idx-1]
    fn accum(&self, mut idx: usize) -> T {
        let mut sum = self.e.clone();
        while idx > 0 {
            sum += self.tree[idx - 1].clone();
            idx &= idx - 1;
        }
        sum
    }
    /// return ∑ d[i] for i in R
    fn sum<R>(&self, interval: R) -> T
    where
        T: std::ops::Sub<Output = T>,
        R: std::ops::RangeBounds<usize>,
    {
        let r = match interval.end_bound() {
            std::ops::Bound::Excluded(&a) => a,
            std::ops::Bound::Included(&a) => a + 1,
            _ => self.n,
        };
        match interval.start_bound() {
            std::ops::Bound::Included(&l) => self.accum(r) - self.accum(l),
            _ => self.accum(r),
        }
    }
}

const MOD: i64 = 998244353;
#[derive(Copy, Clone, Debug)]
pub struct Mint(i64);
impl Mint {
    fn new(x: i64) -> Self {
        Mint(x.rem_euclid(MOD))
    }
    fn pow(self, n: usize) -> Self {
        match n {
            0 => Mint::new(1),
            _ => {
                let mut a = self.pow(n >> 1);
                a *= a;
                if n & 1 == 1 {
                    a *= self;
                }
                a
            }
        }
    }
    fn inv(self) -> Self {
        self.pow((MOD - 2) as usize)
    }
}
impl std::ops::Neg for Mint {
    type Output = Mint;
    fn neg(self) -> Self::Output {
        Self::new(-self.0)
    }
}
impl std::ops::AddAssign<Mint> for Mint {
    fn add_assign(&mut self, rhs: Self) {
        self.0 += rhs.0;
        self.0 %= MOD;
    }
}
impl std::ops::AddAssign<i64> for Mint {
    fn add_assign(&mut self, rhs: i64) {
        *self += Mint::new(rhs);
    }
}
impl<T> std::ops::Add<T> for Mint
where
    Mint: std::ops::AddAssign<T>,
{
    type Output = Self;
    fn add(self, other: T) -> Self {
        let mut res = self;
        res += other;
        res
    }
}
impl std::ops::SubAssign<Mint> for Mint {
    fn sub_assign(&mut self, rhs: Self) {
        self.0 -= rhs.0;
        if self.0 < 0 {
            self.0 += MOD;
        }
    }
}
impl std::ops::SubAssign<i64> for Mint {
    fn sub_assign(&mut self, rhs: i64) {
        *self -= Mint::new(rhs);
    }
}
impl<T> std::ops::Sub<T> for Mint
where
    Mint: std::ops::SubAssign<T>,
{
    type Output = Self;
    fn sub(self, other: T) -> Self {
        let mut res = self;
        res -= other;
        res
    }
}
impl std::ops::MulAssign<Mint> for Mint {
    fn mul_assign(&mut self, rhs: Self) {
        self.0 *= rhs.0;
        self.0 %= MOD;
    }
}
impl std::ops::MulAssign<i64> for Mint {
    fn mul_assign(&mut self, rhs: i64) {
        *self *= Mint::new(rhs);
    }
}
impl<T> std::ops::Mul<T> for Mint
where
    Mint: std::ops::MulAssign<T>,
{
    type Output = Self;
    fn mul(self, other: T) -> Self {
        let mut res = self;
        res *= other;
        res
    }
}
impl std::ops::DivAssign<Mint> for Mint {
    fn div_assign(&mut self, rhs: Self) {
        *self *= rhs.inv();
    }
}
impl std::ops::DivAssign<i64> for Mint {
    fn div_assign(&mut self, rhs: i64) {
        *self /= Mint::new(rhs);
    }
}
impl<T> std::ops::Div<T> for Mint
where
    Mint: std::ops::DivAssign<T>,
{
    type Output = Self;
    fn div(self, other: T) -> Self {
        let mut res = self;
        res /= other;
        res
    }
}
impl std::fmt::Display for Mint {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}
impl std::ops::Deref for Mint {
    type Target = i64;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl std::ops::DerefMut for Mint {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}


Measured memory_bytes: 3600