use std::{cell::{Cell, RefCell, UnsafeCell}, cmp::{Reverse, max, min}, collections::{BTreeMap, BinaryHeap, HashMap, HashSet}, error::Error, fmt::Display, hash::{Hash, Hasher}, io::{BufWriter, Read, Stdin, Stdout, Write}, iter::Peekable, mem::swap, ops::{Not, Sub}, process::exit, rc::Rc, str::{FromStr, from_utf8, from_utf8_unchecked}};

const IO_BUF_SIZE: usize = 1 << 16;
type Input = Scanner<Stdin>;
type Output = BufWriter<Stdout>;
fn _init_input() -> Input { Scanner::new(std::io::stdin()) }
fn _init_output() -> Output { BufWriter::with_capacity(IO_BUF_SIZE, std::io::stdout()) }

#[repr(transparent)] struct Unsync<T>(T);
unsafe impl<T> Sync for Unsync<T> {}

type BadLazy<T> = Unsync<RefCell<Option<T>>>;
impl<T> BadLazy<T> {
    const fn new() -> Self { Self(RefCell::new(None)) }
}

static INPUT: BadLazy<Input> = BadLazy::new();
static OUTPUT: BadLazy<Output> = BadLazy::new();

fn inp<F: FnOnce(&mut Input) -> R, R>(f: F) -> R {
    f(INPUT.0.borrow_mut().get_or_insert_with(_init_input))
}
fn out<F: FnOnce(&mut Output) -> R, R>(f: F) -> R {
    f(OUTPUT.0.borrow_mut().get_or_insert_with(_init_output))
}

macro_rules! read {
    () => { read(); };
    ($t: ty) => { read::<$t>(); };
    ($t: ty, $($tt: ty),*) => { (read::<$t>(), $(read::<$t>(),)*); };
    [$t: ty; $n: expr] => { read_vec::<$t>($n); };
}
macro_rules! println {
    () => { out(|x| writeln!(x).unwrap()); };
    ($exp: expr) => { out(|x| writeln!(x, "{}", $exp).unwrap()); };
    ($fmt: expr, $($arg : tt )*) => { out(|x| writeln!(x, $fmt, $($arg)*).unwrap()); }
}
macro_rules! print {
    ($exp: expr) => { out(|x| write!(x, "{}", $exp).unwrap()); };
    ($fmt: expr, $($arg : tt )*) => { out(|x| write!(x, $fmt, $($arg)*).unwrap()); }
}

fn out_flush() { out(|x| x.flush().unwrap()); }

fn input_is_eof() -> bool { inp(|x| x.eof()) }
fn read_byte() -> u8 { inp(|x| x.byte()) }
fn read_bytes_no_skip(n: usize) -> Vec<u8> { inp(|x| x.bytes_no_skip(n)) }
fn read_bytes(n: usize) -> Vec<u8> { inp(|x| x.bytes(n)) }
fn read_bytes2(n: usize, m: usize) -> Vec<Vec<u8>> { inp(|x| x.bytes2(n, m)) }
fn read_token() -> Vec<u8> { inp(|x| x.token_bytes()) }
fn read_token_str() -> String { unsafe { String::from_utf8_unchecked(read_token()) } }
fn read_line() -> Vec<u8> { inp(|x| x.line_bytes()) }
fn read_line_str() -> String { unsafe { String::from_utf8_unchecked(read_line()) } }
fn read<T: FromStr>() -> T { read_token_str().parse::<T>().ok().unwrap() }
fn read_vec<T: FromStr>(n: usize) -> Vec<T> { (0..n).map(|_| read()).collect() }
fn read_vec2<T: FromStr>(n: usize, m: usize) -> Vec<Vec<T>> { (0..n).map(|_| read_vec(m)).collect() }

struct Scanner<R: Read> {
    src: R,
    _buf: Vec<u8>,
    _pt: usize, // pointer
    _rd: usize, // bytes read
}

#[allow(dead_code)]
impl<R: Read> Scanner<R> {
    fn new(src: R) -> Scanner<R> {
        Scanner { src, _buf: vec![0; IO_BUF_SIZE], _pt: 1, _rd: 1 }
    }

    fn _check_buf(&mut self) {
        if self._pt == self._rd {
            self._rd = self.src.read(&mut self._buf).unwrap_or(0);
            self._pt = (self._rd == 0) as usize;
        }
    }

    // returns true if end of file
    fn eof(&mut self) -> bool {
        self._check_buf();
        self._rd == 0
    }

    // filters \r, returns \0 if eof
    fn byte(&mut self) -> u8 {
        loop {
            self._check_buf();
            if self._rd == 0 { return 0; }
            let res = self._buf[self._pt];
            self._pt += 1;
            if res != b'\r' { return res; }
        }
    }

    fn bytes_no_skip(&mut self, n: usize) -> Vec<u8> { (0..n).map(|_| self.byte()).collect() }
    fn bytes(&mut self, n: usize) -> Vec<u8> {
        let res = self.bytes_no_skip(n);
        self.byte();
        res
    }
    fn bytes2(&mut self, n: usize, m: usize) -> Vec<Vec<u8>> { (0..n).map(|_| self.bytes(m)).collect() }

    fn token_bytes(&mut self) -> Vec<u8> {
        let mut res = Vec::new();
        let mut c = self.byte();
        while c <= b' ' {
            if c == b'\0' { return res; }
            c = self.byte();
        }
        loop {
            res.push(c);
            c = self.byte();
            if c <= b' ' { return res; }
        }
    }

    fn line_bytes(&mut self) -> Vec<u8> {
        let mut res = Vec::new();
        let mut c = self.byte();
        while c != b'\n' && c != b'\0' {
            res.push(c);
            c = self.byte();
        }
        res
    }
}
trait JoinToStr {
    fn join_to_str(&mut self, sep: &str) -> String;
    fn concat_to_str(&mut self) -> String;
}
impl<T: ToString, I: Iterator<Item = T>> JoinToStr for I {
    fn join_to_str(&mut self, sep: &str) -> String {
        let mut res = String::new();
        match self.next() {
            None => res,
            Some(first) => {
                res.push_str(&first.to_string());
                loop {
                    match self.next() {
                        None => break,
                        Some(item) => {
                            res.push_str(sep);
                            res.push_str(&item.to_string())
                        }
                    }
                }
                res
            }
        }
    }

    fn concat_to_str(&mut self) -> String {
        let mut res = String::new();
        for item in self { res.push_str(&item.to_string()); }
        res
    }
}

macro_rules! veci {
    ($n:expr , $i:ident : $gen:expr) => {{
        let n = $n;
        let mut list = Vec::with_capacity(n);
        for $i in 0..n {
            list.push($gen);
        }
        list
    }};
    ($n:expr , $gen:expr) => { veci!($n, __: $gen); }
}

fn abs_diff<T: Sub<Output = T> + PartialOrd>(x: T, y: T) -> T {
    if x < y { y - x } else { x - y }
}

// * end commons * //

mod modint {

    use std::{convert::Infallible, iter::Sum, mem::swap, ops::AddAssign};

    pub trait RemEuclidU32: Copy {
        /// Calculates `self` _mod_ `modulus` losslessly.
        fn rem_euclid_u32(self, modulus: u32) -> u32;

        fn pow_mod(self, exponent: u64, modulus: u32) -> u32 {
            pow_mod_raw(self.rem_euclid_u32(modulus), exponent, modulus)
        }
        fn mul_mod<Rhs: RemEuclidU32>(self, rhs: Rhs, modulus: u32) -> u32 {
            mul_mod_u32(self.rem_euclid_u32(modulus), rhs.rem_euclid_u32(modulus), modulus)
        }

        fn mod_pow_vec(self, n: usize, modulus: u32) -> Vec<u32> {
            let a = self.rem_euclid_u32(modulus);
            let mut res = vec![0u32; n+1];
            if modulus == 1 { return res; }
            res[0] = 1;
            for i in 1..=n {
                res[i] = mul_mod_u32(a, res[i-1], modulus);
            }
            res
        }
    }

    macro_rules! impl_rem_euclid_u32_for_small_signed {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        (self as i64).rem_euclid(i64::from(modulus)) as _
                    }
                }
            )*
        }
    }

    impl_rem_euclid_u32_for_small_signed!(i8, i16, i32, i64, isize);

    impl RemEuclidU32 for i128 {
        #[inline]
        fn rem_euclid_u32(self, modulus: u32) -> u32 {
            self.rem_euclid(i128::from(modulus)) as _
        }
    }

    macro_rules! impl_rem_euclid_u32_for_small_unsigned {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        self as u32 % modulus
                    }
                }
            )*
        }
    }

    macro_rules! impl_rem_euclid_u32_for_large_unsigned {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        (self % (modulus as $ty)) as _
                    }
                }
            )*
        }
    }

    impl_rem_euclid_u32_for_small_unsigned!(u8, u16, u32);
    impl_rem_euclid_u32_for_large_unsigned!(u64, u128);

    #[cfg(target_pointer_width = "32")]
    impl_rem_euclid_u32_for_small_unsigned!(usize);

    #[cfg(target_pointer_width = "64")]
    impl_rem_euclid_u32_for_large_unsigned!(usize);
    #[inline]
    pub fn mul_mod_u32(a: u32, b: u32, m: u32) -> u32 {
        ((a as u64) * (b as u64) % (m as u64)) as u32
    }

    // for a, b < m, undefined otherwise
    #[inline]
    pub fn add_mod_raw(a: u32, b: u32, m: u32) -> u32 {
        sub_mod_raw(a, m-b, m)
    }
    #[inline]
    pub fn sub_mod_raw(a: u32, b: u32, m: u32) -> u32 {
        let (r, c) = a.overflowing_sub(b);
        if c { r.wrapping_add(m) } else { r }
    }
    pub fn pow_mod_raw(a: u32, mut k: u64, m: u32) -> u32 {
        if m == 1 { return 0; }
        let mut a = a as u64;
        let m = m as u64;
        let mut r: u64 = 1;
        while k > 0 {
            if k & 1 == 1 {
                r = r * a % m;
            }
            k >>= 1;
            a = a * a % m;
        }
        return r as u32;
    }

    /// # Parameters
    /// * `b` `1 <= b`
    /// # Returns
    /// (x, g) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
    pub fn inv_gcd(a: i64, b: i64) -> (i64, i64) {
        let a = a.rem_euclid(b);
        if a == 0 { return (0, b); }
        let mut s = b;
        let mut t = a;
        let mut m0 = 0;
        let mut m1 = 1;

        while t != 0 {
            let u = s / t;
            s -= t * u;
            m0 -= m1 * u;
            std::mem::swap(&mut s, &mut t);
            std::mem::swap(&mut m0, &mut m1);
        }

        if m0 < 0 { m0 += b / s; }
        (m0, s)
    }

    #[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
    #[repr(transparent)]
    pub struct ModInt { pub val: u32 }

    impl ModInt {
        #[inline(always)]
        pub fn modulus() -> u32 { crate::get_modulus() }
        pub fn new<I: RemEuclidU32>(val: I) -> Self { Self::raw(val.rem_euclid_u32(Self::modulus())) }
        #[inline]
        pub fn raw(val: u32) -> Self { Self { val } }
        pub fn inv(self) -> Self {
            let (x, gcd) = inv_gcd(self.val.into(), Self::modulus().into());
            if gcd != 1 { panic!("the multiplicative inverse {}^-1 mod {} does not exist", self.val, Self::modulus()) }
            Self::raw(x as u32)
        }
        pub fn pow(self, k: u64) -> Self {
            Self::raw(pow_mod_raw(self.val, k, Self::modulus()))
        }
        pub fn pow_vec(self, n: usize) -> Vec<Self> {
            let mut res = vec![Self::raw(0); n+1];
            res[0] += 1;
            for i in 1..=n {
                res[i] = res[i-1] * self;
            }
            res
        }
    }

    #[inline]
    pub fn mi<I: RemEuclidU32>(val: I) -> ModInt { ModInt::new(val) }

    impl<V: RemEuclidU32> From<V> for ModInt {
        #[inline]
        fn from(from: V) -> Self { Self::new(from) }
    }
    impl std::str::FromStr for ModInt {
        type Err = std::convert::Infallible;
        #[inline]
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            Ok(s.parse::<i64>()
            .map(Self::new)
            .unwrap_or_else(|_| todo!("parsing as an arbitrary precision integer?")))
        }
    }
    impl std::fmt::Display for ModInt {
        #[inline]
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            std::fmt::Display::fmt(&self.val, f)
        }
    }
    impl std::fmt::Debug for ModInt {
        #[inline]
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            std::fmt::Debug::fmt(&self.val, f)
        }
    }
    impl std::ops::Neg for ModInt {
        type Output = ModInt;

        #[inline]
        fn neg(self) -> Self::Output {
            Self::raw(0) - self
            //Self::raw(norm(self.val.wrapping_neg(), Self::modulus()))
        }
    }

    impl std::ops::Add for ModInt {
        type Output = ModInt;
        #[inline]
        fn add(self, rhs: Self) -> Self::Output {
            Self::raw(add_mod_raw(self.val, rhs.val, Self::modulus()))
        }
    }
    impl std::ops::Sub for ModInt {
        type Output = ModInt;
        #[inline]
        fn sub(self, rhs: Self) -> Self::Output {
            Self::raw(sub_mod_raw(self.val, rhs.val, Self::modulus()))
        }
    }
    impl std::ops::Mul for ModInt {
        type Output = ModInt;
        #[inline]
        fn mul(self, rhs: Self) -> Self::Output {
            Self::raw(mul_mod_u32(self.val, rhs.val, Self::modulus()))
        }
    }
    impl std::ops::Div for ModInt {
        type Output = ModInt;
        #[inline]
        fn div(self, rhs: Self) -> Self::Output { self * rhs.inv() }
    }

    impl <I: RemEuclidU32> std::ops::Add<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn add(self, rhs: I) -> Self::Output { self + Self::new(rhs) }
    }
    impl <I: RemEuclidU32> std::ops::Sub<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn sub(self, rhs: I) -> Self::Output { self - Self::new(rhs) }
    }
    impl <I: RemEuclidU32> std::ops::Mul<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn mul(self, rhs: I) -> Self::Output { self * Self::new(rhs) }
    }
    impl <I: RemEuclidU32> std::ops::Div<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn div(self, rhs: I) -> Self::Output { self / Self::new(rhs) }
    }

    impl std::ops::AddAssign for ModInt {
        #[inline]
        fn add_assign(&mut self, rhs: Self) { *self = *self + rhs; }
    }
    impl std::ops::SubAssign for ModInt {
        #[inline]
        fn sub_assign(&mut self, rhs: Self) { *self = *self - rhs; }
    }
    impl std::ops::MulAssign for ModInt {
        #[inline]
        fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs; }
    }
    impl std::ops::DivAssign for ModInt {
        #[inline]
        fn div_assign(&mut self, rhs: Self) { *self = *self / rhs; }
    }
    impl <I: RemEuclidU32> std::ops::AddAssign<I> for ModInt {
        #[inline]
        fn add_assign(&mut self, rhs: I) { *self = *self + rhs; }
    }
    impl <I: RemEuclidU32> std::ops::SubAssign<I> for ModInt {
        #[inline]
        fn sub_assign(&mut self, rhs: I) { *self = *self - rhs; }
    }
    impl <I: RemEuclidU32> std::ops::MulAssign<I> for ModInt {
        #[inline]
        fn mul_assign(&mut self, rhs: I) { *self = *self * rhs; }
    }
    impl <I: RemEuclidU32> std::ops::DivAssign<I> for ModInt {
        #[inline]
        fn div_assign(&mut self, rhs: I) { *self = *self / rhs; }
    }

    impl std::iter::Sum for ModInt {
        #[inline] fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(Self::raw(0), std::ops::Add::add)
        }
    }
    impl std::iter::Product for ModInt {
        #[inline] fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(1.into(), std::ops::Mul::mul)
        }
    }
    impl<'a> std::iter::Sum<&'a Self> for ModInt {
        #[inline] fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> ModInt {
            iter.fold(Self::raw(0), |a, &b| a + b)
        }
    }
    impl<'a> std::iter::Product<&'a Self> for ModInt {
        #[inline] fn product<I: Iterator<Item = &'a Self>>(iter: I) -> ModInt {
            iter.fold(1.into(), |a, &b| a * b)
        }
    }
}

// const MODULUS: u32 = 998_244_353;
// //const MODULUS: u32 = 1_000_000_007;
// #[inline(always)]
// fn get_modulus() -> u32 { MODULUS }

static MODULUS: Unsync<Cell<u32>> = Unsync(Cell::new(0));
#[inline] fn get_modulus() -> u32 { MODULUS.0.get() }
#[inline] fn set_modulus(value: u32) { MODULUS.0.set(value) }

use crate::modint::*;

#[allow(non_snake_case, unused_macros)]
fn main() -> Result<(), Box<dyn Error>> {
    let num_cases = 1;//read!(i32);

    for _case_num in 1..=num_cases {
        let n = read!(usize);
        set_modulus(read!());

        let mut dp = vec![mi(0); n+1];
        dp[1] = mi(1);
        dp[2] = mi(2);
        for i in 2..n {
            let d = dp[i];
            dp[i+1] += d + d + 1;
            let d = d - dp[i-1];
            for j in (i*2..=n).step_by(i) {
                dp[j] += d;
            }
        }

        let ans = dp[n];
        println!(ans); //
    }

    out_flush();
    Ok(())
}


use std::{cell::{Cell, RefCell, UnsafeCell}, cmp::{Reverse, max, min}, collections::{BTreeMap, BinaryHeap, HashMap, HashSet}, error::Error, fmt::Display, hash::{Hash, Hasher}, io::{BufWriter, Read, Stdin, Stdout, Write}, iter::Peekable, mem::swap, ops::{Not, Sub}, process::exit, rc::Rc, str::{FromStr, from_utf8, from_utf8_unchecked}};

const IO_BUF_SIZE: usize = 1 << 16;
type Input = Scanner<Stdin>;
type Output = BufWriter<Stdout>;
fn _init_input() -> Input { Scanner::new(std::io::stdin()) }
fn _init_output() -> Output { BufWriter::with_capacity(IO_BUF_SIZE, std::io::stdout()) }

#[repr(transparent)] struct Unsync<T>(T);
unsafe impl<T> Sync for Unsync<T> {}

type BadLazy<T> = Unsync<UnsafeCell<Option<T>>>;
impl<T> BadLazy<T> {
    const fn new() -> Self { Self(UnsafeCell::new(None)) }
}

static INPUT: BadLazy<Input> = BadLazy::new();
static OUTPUT: BadLazy<Output> = BadLazy::new();

fn inp<F: FnOnce(&mut Input) -> R, R>(f: F) -> R {
    unsafe { f((&mut *INPUT.0.get()).get_or_insert_with(_init_input)) }
}
fn out<F: FnOnce(&mut Output) -> R, R>(f: F) -> R {
    unsafe { f((&mut *OUTPUT.0.get()).get_or_insert_with(_init_output)) }
}

macro_rules! read {
    () => { read(); };
    ($t: ty) => { read::<$t>(); };
    ($t: ty, $($tt: ty),*) => { (read::<$t>(), $(read::<$t>(),)*); };
    [$t: ty; $n: expr] => { read_vec::<$t>($n); };
}
macro_rules! println {
    () => { out(|x| writeln!(x).unwrap()); };
    ($exp: expr) => { out(|x| writeln!(x, "{}", $exp).unwrap()); };
    ($fmt: expr, $($arg : tt )*) => { out(|x| writeln!(x, $fmt, $($arg)*).unwrap()); }
}
macro_rules! print {
    ($exp: expr) => { out(|x| write!(x, "{}", $exp).unwrap()); };
    ($fmt: expr, $($arg : tt )*) => { out(|x| write!(x, $fmt, $($arg)*).unwrap()); }
}

fn out_flush() { out(|x| x.flush().unwrap()); }

fn input_is_eof() -> bool { inp(|x| x.eof()) }
fn read_byte() -> u8 { inp(|x| x.byte()) }
fn read_bytes_no_skip(n: usize) -> Vec<u8> { inp(|x| x.bytes_no_skip(n)) }
fn read_bytes(n: usize) -> Vec<u8> { inp(|x| x.bytes(n)) }
fn read_bytes2(n: usize, m: usize) -> Vec<Vec<u8>> { inp(|x| x.bytes2(n, m)) }
fn read_token() -> Vec<u8> { inp(|x| x.token_bytes()) }
fn read_token_str() -> String { unsafe { String::from_utf8_unchecked(read_token()) } }
fn read_line() -> Vec<u8> { inp(|x| x.line_bytes()) }
fn read_line_str() -> String { unsafe { String::from_utf8_unchecked(read_line()) } }
fn read<T: FromStr>() -> T { read_token_str().parse::<T>().ok().unwrap() }
fn read_vec<T: FromStr>(n: usize) -> Vec<T> { (0..n).map(|_| read()).collect() }
fn read_vec2<T: FromStr>(n: usize, m: usize) -> Vec<Vec<T>> { (0..n).map(|_| read_vec(m)).collect() }

struct Scanner<R: Read> {
    src: R,
    _buf: Vec<u8>,
    _pt: usize, // pointer
    _rd: usize, // bytes read
}

#[allow(dead_code)]
impl<R: Read> Scanner<R> {
    fn new(src: R) -> Scanner<R> {
        Scanner { src, _buf: vec![0; IO_BUF_SIZE], _pt: 1, _rd: 1 }
    }

    fn _check_buf(&mut self) {
        if self._pt == self._rd {
            self._rd = self.src.read(&mut self._buf).unwrap_or(0);
            self._pt = (self._rd == 0) as usize;
        }
    }

    // returns true if end of file
    fn eof(&mut self) -> bool {
        self._check_buf();
        self._rd == 0
    }

    // filters \r, returns \0 if eof
    fn byte(&mut self) -> u8 {
        loop {
            self._check_buf();
            if self._rd == 0 { return 0; }
            let res = self._buf[self._pt];
            self._pt += 1;
            if res != b'\r' { return res; }
        }
    }

    fn bytes_no_skip(&mut self, n: usize) -> Vec<u8> { (0..n).map(|_| self.byte()).collect() }
    fn bytes(&mut self, n: usize) -> Vec<u8> {
        let res = self.bytes_no_skip(n);
        self.byte();
        res
    }
    fn bytes2(&mut self, n: usize, m: usize) -> Vec<Vec<u8>> { (0..n).map(|_| self.bytes(m)).collect() }

    fn token_bytes(&mut self) -> Vec<u8> {
        let mut res = Vec::new();
        let mut c = self.byte();
        while c <= b' ' {
            if c == b'\0' { return res; }
            c = self.byte();
        }
        loop {
            res.push(c);
            c = self.byte();
            if c <= b' ' { return res; }
        }
    }

    fn line_bytes(&mut self) -> Vec<u8> {
        let mut res = Vec::new();
        let mut c = self.byte();
        while c != b'\n' && c != b'\0' {
            res.push(c);
            c = self.byte();
        }
        res
    }
}
trait JoinToStr {
    fn join_to_str(&mut self, sep: &str) -> String;
    fn concat_to_str(&mut self) -> String;
}
impl<T: ToString, I: Iterator<Item = T>> JoinToStr for I {
    fn join_to_str(&mut self, sep: &str) -> String {
        let mut res = String::new();
        match self.next() {
            None => res,
            Some(first) => {
                res.push_str(&first.to_string());
                loop {
                    match self.next() {
                        None => break,
                        Some(item) => {
                            res.push_str(sep);
                            res.push_str(&item.to_string())
                        }
                    }
                }
                res
            }
        }
    }

    fn concat_to_str(&mut self) -> String {
        let mut res = String::new();
        for item in self { res.push_str(&item.to_string()); }
        res
    }
}

macro_rules! veci {
    ($n:expr , $i:ident : $gen:expr) => {{
        let n = $n;
        let mut list = Vec::with_capacity(n);
        for $i in 0..n {
            list.push($gen);
        }
        list
    }};
    ($n:expr , $gen:expr) => { veci!($n, __: $gen); }
}

fn abs_diff<T: Sub<Output = T> + PartialOrd>(x: T, y: T) -> T {
    if x < y { y - x } else { x - y }
}

// * end commons * //

mod modint {

    use std::{convert::Infallible, iter::Sum, mem::swap, ops::AddAssign};

    pub trait RemEuclidU32: Copy {
        /// Calculates `self` _mod_ `modulus` losslessly.
        fn rem_euclid_u32(self, modulus: u32) -> u32;

        fn pow_mod(self, exponent: u64, modulus: u32) -> u32 {
            pow_mod_raw(self.rem_euclid_u32(modulus), exponent, modulus)
        }
        fn mul_mod<Rhs: RemEuclidU32>(self, rhs: Rhs, modulus: u32) -> u32 {
            mul_mod_u32(self.rem_euclid_u32(modulus), rhs.rem_euclid_u32(modulus), modulus)
        }

        fn mod_pow_vec(self, n: usize, modulus: u32) -> Vec<u32> {
            let a = self.rem_euclid_u32(modulus);
            let mut res = vec![0u32; n+1];
            if modulus == 1 { return res; }
            res[0] = 1;
            for i in 1..=n {
                res[i] = mul_mod_u32(a, res[i-1], modulus);
            }
            res
        }
    }

    macro_rules! impl_rem_euclid_u32_for_small_signed {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        (self as i64).rem_euclid(i64::from(modulus)) as _
                    }
                }
            )*
        }
    }

    impl_rem_euclid_u32_for_small_signed!(i8, i16, i32, i64, isize);

    impl RemEuclidU32 for i128 {
        #[inline]
        fn rem_euclid_u32(self, modulus: u32) -> u32 {
            self.rem_euclid(i128::from(modulus)) as _
        }
    }

    macro_rules! impl_rem_euclid_u32_for_small_unsigned {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        self as u32 % modulus
                    }
                }
            )*
        }
    }

    macro_rules! impl_rem_euclid_u32_for_large_unsigned {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        (self % (modulus as $ty)) as _
                    }
                }
            )*
        }
    }

    impl_rem_euclid_u32_for_small_unsigned!(u8, u16, u32);
    impl_rem_euclid_u32_for_large_unsigned!(u64, u128);

    #[cfg(target_pointer_width = "32")]
    impl_rem_euclid_u32_for_small_unsigned!(usize);

    #[cfg(target_pointer_width = "64")]
    impl_rem_euclid_u32_for_large_unsigned!(usize);
    #[inline]
    pub fn mul_mod_u32(a: u32, b: u32, m: u32) -> u32 {
        ((a as u64) * (b as u64) % (m as u64)) as u32
    }

    // for a, b < m, undefined otherwise
    #[inline]
    pub fn add_mod_raw(a: u32, b: u32, m: u32) -> u32 {
        sub_mod_raw(a, m-b, m)
    }
    #[inline]
    pub fn sub_mod_raw(a: u32, b: u32, m: u32) -> u32 {
        let (r, c) = a.overflowing_sub(b);
        if c { r.wrapping_add(m) } else { r }
    }
    pub fn pow_mod_raw(a: u32, mut k: u64, m: u32) -> u32 {
        if m == 1 { return 0; }
        let mut a = a as u64;
        let m = m as u64;
        let mut r: u64 = 1;
        while k > 0 {
            if k & 1 == 1 {
                r = r * a % m;
            }
            k >>= 1;
            a = a * a % m;
        }
        return r as u32;
    }

    /// # Parameters
    /// * `b` `1 <= b`
    /// # Returns
    /// (x, g) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
    pub fn inv_gcd(a: i64, b: i64) -> (i64, i64) {
        let a = a.rem_euclid(b);
        if a == 0 { return (0, b); }
        let mut s = b;
        let mut t = a;
        let mut m0 = 0;
        let mut m1 = 1;

        while t != 0 {
            let u = s / t;
            s -= t * u;
            m0 -= m1 * u;
            std::mem::swap(&mut s, &mut t);
            std::mem::swap(&mut m0, &mut m1);
        }

        if m0 < 0 { m0 += b / s; }
        (m0, s)
    }

    #[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
    #[repr(transparent)]
    pub struct ModInt { pub val: u32 }

    impl ModInt {
        #[inline(always)]
        pub fn modulus() -> u32 { crate::get_modulus() }
        #[inline] pub fn new<I: RemEuclidU32>(val: I) -> Self { Self::raw(val.rem_euclid_u32(Self::modulus())) }
        #[inline] pub const fn raw(val: u32) -> Self { Self { val } }
        pub fn inv(self) -> Self {
            let (x, gcd) = inv_gcd(self.val.into(), Self::modulus().into());
            if gcd != 1 { panic!("the multiplicative inverse {}^-1 mod {} does not exist", self.val, Self::modulus()) }
            Self::raw(x as u32)
        }
        #[inline] pub fn pow(self, k: u64) -> Self {
            Self::raw(pow_mod_raw(self.val, k, Self::modulus()))
        }
        pub fn pow_vec(self, n: usize) -> Vec<Self> {
            let mut res = vec![Self::raw(0); n+1];
            res[0] += 1;
            for i in 1..=n {
                res[i] = res[i-1] * self;
            }
            res
        }
    }

    #[inline]
    pub fn mi<I: RemEuclidU32>(val: I) -> ModInt { ModInt::new(val) }

    impl<V: RemEuclidU32> From<V> for ModInt {
        #[inline]
        fn from(from: V) -> Self { Self::new(from) }
    }
    impl std::str::FromStr for ModInt {
        type Err = std::convert::Infallible;
        #[inline]
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            Ok(s.parse::<i64>()
            .map(Self::new)
            .unwrap_or_else(|_| todo!("parsing as an arbitrary precision integer?")))
        }
    }
    impl std::fmt::Display for ModInt {
        #[inline]
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            std::fmt::Display::fmt(&self.val, f)
        }
    }
    impl std::fmt::Debug for ModInt {
        #[inline]
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            std::fmt::Debug::fmt(&self.val, f)
        }
    }
    impl std::ops::Neg for ModInt {
        type Output = ModInt;

        #[inline]
        fn neg(self) -> Self::Output {
            Self::raw(0) - self
            //Self::raw(norm(self.val.wrapping_neg(), Self::modulus()))
        }
    }

    impl std::ops::Add for ModInt {
        type Output = ModInt;
        #[inline]
        fn add(self, rhs: Self) -> Self::Output {
            Self::raw(add_mod_raw(self.val, rhs.val, Self::modulus()))
        }
    }
    impl std::ops::Sub for ModInt {
        type Output = ModInt;
        #[inline]
        fn sub(self, rhs: Self) -> Self::Output {
            Self::raw(sub_mod_raw(self.val, rhs.val, Self::modulus()))
        }
    }
    impl std::ops::Mul for ModInt {
        type Output = ModInt;
        #[inline]
        fn mul(self, rhs: Self) -> Self::Output {
            Self::raw(mul_mod_u32(self.val, rhs.val, Self::modulus()))
        }
    }
    impl std::ops::Div for ModInt {
        type Output = ModInt;
        #[inline]
        fn div(self, rhs: Self) -> Self::Output { self * rhs.inv() }
    }

    impl <I: RemEuclidU32> std::ops::Add<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn add(self, rhs: I) -> Self::Output { self + Self::new(rhs) }
    }
    impl <I: RemEuclidU32> std::ops::Sub<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn sub(self, rhs: I) -> Self::Output { self - Self::new(rhs) }
    }
    impl <I: RemEuclidU32> std::ops::Mul<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn mul(self, rhs: I) -> Self::Output { self * Self::new(rhs) }
    }
    impl <I: RemEuclidU32> std::ops::Div<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn div(self, rhs: I) -> Self::Output { self / Self::new(rhs) }
    }

    impl std::ops::AddAssign for ModInt {
        #[inline]
        fn add_assign(&mut self, rhs: Self) { *self = *self + rhs; }
    }
    impl std::ops::SubAssign for ModInt {
        #[inline]
        fn sub_assign(&mut self, rhs: Self) { *self = *self - rhs; }
    }
    impl std::ops::MulAssign for ModInt {
        #[inline]
        fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs; }
    }
    impl std::ops::DivAssign for ModInt {
        #[inline]
        fn div_assign(&mut self, rhs: Self) { *self = *self / rhs; }
    }
    impl <I: RemEuclidU32> std::ops::AddAssign<I> for ModInt {
        #[inline]
        fn add_assign(&mut self, rhs: I) { *self = *self + rhs; }
    }
    impl <I: RemEuclidU32> std::ops::SubAssign<I> for ModInt {
        #[inline]
        fn sub_assign(&mut self, rhs: I) { *self = *self - rhs; }
    }
    impl <I: RemEuclidU32> std::ops::MulAssign<I> for ModInt {
        #[inline]
        fn mul_assign(&mut self, rhs: I) { *self = *self * rhs; }
    }
    impl <I: RemEuclidU32> std::ops::DivAssign<I> for ModInt {
        #[inline]
        fn div_assign(&mut self, rhs: I) { *self = *self / rhs; }
    }

    impl std::iter::Sum for ModInt {
        #[inline] fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(Self::raw(0), std::ops::Add::add)
        }
    }
    impl std::iter::Product for ModInt {
        #[inline] fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(1.into(), std::ops::Mul::mul)
        }
    }
    impl<'a> std::iter::Sum<&'a Self> for ModInt {
        #[inline] fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> ModInt {
            iter.fold(Self::raw(0), |a, &b| a + b)
        }
    }
    impl<'a> std::iter::Product<&'a Self> for ModInt {
        #[inline] fn product<I: Iterator<Item = &'a Self>>(iter: I) -> ModInt {
            iter.fold(1.into(), |a, &b| a * b)
        }
    }
}

// const MODULUS: u32 = 998_244_353;
// //const MODULUS: u32 = 1_000_000_007;
// #[inline(always)]
// fn get_modulus() -> u32 { MODULUS }

static MODULUS: Unsync<Cell<u32>> = Unsync(Cell::new(0));
#[inline] fn get_modulus() -> u32 { MODULUS.0.get() }
#[inline] fn set_modulus(value: u32) { MODULUS.0.set(value) }

use crate::modint::*;

#[inline] const fn mir(v: u32) -> ModInt { ModInt::raw(v) }

#[allow(non_snake_case, unused_macros)]
fn main() -> Result<(), Box<dyn Error>> {
    let num_cases = 1;//read!(i32);

    for _case_num in 1..=num_cases {
        let n = read!(usize);
        set_modulus(read!());

        let mut dp = vec![mir(0); n+1];
        dp[1] = mir(1);
        dp[2] = mir(2);
        for i in 2..n {
            let d = dp[i];
            dp[i+1] += d + d + mir(1);
            let d = d - dp[i-1];
            for j in (i*2..=n).step_by(i) {
                dp[j] += d;
            }
        }

        let ans = dp[n];
        println!(ans); //
    }

    out_flush();
    Ok(())
}


use std::{cell::Cell, cmp::{Reverse, max, min}, collections::{BTreeMap, HashMap, HashSet}, error::Error, fmt::Display, io::{BufWriter, Read, Write}, iter::Peekable, mem::swap, ops::{Not, Range, RangeInclusive, Sub}, process::exit, rc::Rc, str::{FromStr, from_utf8, from_utf8_unchecked}};

const IO_BUF_SIZE: usize = 1 << 16;
struct Scanner<'a, R: Read> {
    src: &'a mut R,
    _buf: Vec<u8>,
    _pt: usize, // pointer
    _rd: usize, // bytes read
}

#[allow(dead_code)]
impl<'a, R: Read> Scanner<'a, R> {
    fn new(src: &'a mut R) -> Scanner<'a, R> {
        Scanner { src, _buf: vec![0; IO_BUF_SIZE], _pt: 1, _rd: 1 }
    }

    fn _check_buf(&mut self) {
        if self._pt == self._rd {
            self._rd = self.src.read(&mut self._buf).unwrap_or(0);
            self._pt = (self._rd == 0) as usize;
        }
    }

    // returns true if end of file
    fn eof(&mut self) -> bool {
        self._check_buf();
        self._rd == 0
    }

    // filters \r, returns \0 if eof
    fn byte(&mut self) -> u8 {
        loop {
            self._check_buf();
            if self._rd == 0 { return 0; }
            let res = self._buf[self._pt];
            self._pt += 1;
            if res != b'\r' { return res; }
        }
    }

    fn char(&mut self) -> char { self.byte() as char }
    fn bytes_no_skip(&mut self, n: usize) -> Vec<u8> { (0..n).map(|_| self.byte()).collect() }
    fn bytes(&mut self, n: usize) -> Vec<u8> {
        let res = self.bytes_no_skip(n);
        self.byte();
        res
    }
    fn bytes2(&mut self, n: usize, m: usize) -> Vec<Vec<u8>> { (0..n).map(|_| self.bytes(m)).collect() }

    fn token_bytes(&mut self) -> Vec<u8> {
        let mut res = Vec::new();
        let mut c = self.byte();
        while c <= b' ' {
            if c == b'\0' { return res; }
            c = self.byte();
        }
        loop {
            res.push(c);
            c = self.byte();
            if c <= b' ' { return res; }
        }
    }
    fn token(&mut self) -> String { unsafe { String::from_utf8_unchecked(self.token_bytes()) } }

    fn line_bytes(&mut self) -> Vec<u8> {
        let mut res = Vec::new();
        let mut c = self.byte();
        while c != b'\n' && c != b'\0' {
            res.push(c);
            c = self.byte();
        }
        res
    }
    fn line(&mut self) -> String { unsafe { String::from_utf8_unchecked(self.line_bytes()) } }

    fn read<T: FromStr>(&mut self) -> T {
        let token = self.token_bytes();
        unsafe { from_utf8_unchecked(&token).parse::<T>().ok().unwrap()  }
    }
    fn vec<T: FromStr>(&mut self, n: usize) -> Vec<T> { (0..n).map(|_| self.read()).collect() }
    fn vec2<T: FromStr>(&mut self, n: usize, m: usize) -> Vec<Vec<T>> { (0..n).map(|_| self.vec(m)).collect() }
}

trait ToCharVec { fn to_char_vec(&self) -> Vec<char>; }
impl ToCharVec for &str { fn to_char_vec(&self) -> Vec<char> { self.chars().collect() } }
impl ToCharVec for String { fn to_char_vec(&self) -> Vec<char> { self.chars().collect() } }
trait JoinToStr {
    fn join_to_str(&mut self, sep: &str) -> String;
    fn concat_to_str(&mut self) -> String;
}
impl<T: ToString, I: Iterator<Item = T>> JoinToStr for I {
    fn join_to_str(&mut self, sep: &str) -> String {
        let mut res = String::new();
        match self.next() {
            None => res,
            Some(first) => {
                res.push_str(&first.to_string());
                loop {
                    match self.next() {
                        None => break,
                        Some(item) => {
                            res.push_str(sep);
                            res.push_str(&item.to_string())
                        }
                    }
                }
                res
            }
        }
    }

    fn concat_to_str(&mut self) -> String {
        let mut res = String::new();
        for item in self { res.push_str(&item.to_string()); }
        res
    }
}

macro_rules! veci {
    ($n:expr , $i:ident : $gen:expr) => {{
        let n = $n;
        let mut list = Vec::with_capacity(n);
        for $i in 0..n {
            list.push($gen);
        }
        list
    }};
    ($n:expr , $gen:expr) => { veci!($n, __: $gen); }
}

fn abs_diff<T: Sub<Output = T> + PartialOrd>(x: T, y: T) -> T {
    if x < y { y - x } else { x - y }
}

// * end commons * //

mod modint {

    use std::{convert::Infallible, iter::Sum, mem::swap, ops::AddAssign};

    pub trait RemEuclidU32: Copy {
        /// Calculates `self` _mod_ `modulus` losslessly.
        fn rem_euclid_u32(self, modulus: u32) -> u32;

        fn pow_mod(self, exponent: u64, modulus: u32) -> u32 {
            pow_mod_raw(self.rem_euclid_u32(modulus), exponent, modulus)
        }
        fn mul_mod<Rhs: RemEuclidU32>(self, rhs: Rhs, modulus: u32) -> u32 {
            mul_mod_u32(self.rem_euclid_u32(modulus), rhs.rem_euclid_u32(modulus), modulus)
        }

        fn mod_pow_vec(self, n: usize, modulus: u32) -> Vec<u32> {
            let a = self.rem_euclid_u32(modulus);
            let mut res = vec![0u32; n+1];
            if modulus == 1 { return res; }
            res[0] = 1;
            for i in 1..=n {
                res[i] = mul_mod_u32(a, res[i-1], modulus);
            }
            res
        }
    }

    macro_rules! impl_rem_euclid_u32_for_small_signed {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        (self as i64).rem_euclid(i64::from(modulus)) as _
                    }
                }
            )*
        }
    }

    impl_rem_euclid_u32_for_small_signed!(i8, i16, i32, i64, isize);

    impl RemEuclidU32 for i128 {
        #[inline]
        fn rem_euclid_u32(self, modulus: u32) -> u32 {
            self.rem_euclid(i128::from(modulus)) as _
        }
    }

    macro_rules! impl_rem_euclid_u32_for_small_unsigned {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        self as u32 % modulus
                    }
                }
            )*
        }
    }

    macro_rules! impl_rem_euclid_u32_for_large_unsigned {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        (self % (modulus as $ty)) as _
                    }
                }
            )*
        }
    }

    impl_rem_euclid_u32_for_small_unsigned!(u8, u16, u32);
    impl_rem_euclid_u32_for_large_unsigned!(u64, u128);

    #[cfg(target_pointer_width = "32")]
    impl_rem_euclid_u32_for_small_unsigned!(usize);

    #[cfg(target_pointer_width = "64")]
    impl_rem_euclid_u32_for_large_unsigned!(usize);

    pub fn mul_mod_u32(a: u32, b: u32, m: u32) -> u32 {
        ((a as u64) * (b as u64) % (m as u64)) as u32
    }

    #[inline]
    fn norm(a: u32, m: u32) -> u32 {
        (((a as i32) >> 31) as u32 & m) + a
    }
    // for a, b < m < 2^31, undefined otherwise
    #[inline]
    pub fn add_mod_raw(a: u32, b: u32, m: u32) -> u32 {
        //if b >= m - a { a.wrapping_add(b).wrapping_sub(m) } else { a + b }
        norm(a.wrapping_add(b).wrapping_sub(m), m)
    }
    #[inline]
    pub fn sub_mod_raw(a: u32, b: u32, m: u32) -> u32 {
        //if a < b { a.wrapping_add(m).wrapping_sub(b) } else { a - b }
        norm(a.wrapping_sub(b), m)
    }
    pub fn pow_mod_raw(a: u32, mut k: u64, m: u32) -> u32 {
        if m == 1 { return 0; }
        let mut a= a as u64;
        let m = m as u64;
        let mut r: u64 = 1;
        while k > 0 {
            if k & 1 == 1 {
                r = r * a % m;
            }
            k >>= 1;
            a = a * a % m;
        }
        return r as u32;
    }

    /// # Parameters
    /// * `b` `1 <= b`
    /// # Returns
    /// (x, g) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
    pub fn inv_gcd(a: i64, b: i64) -> (i64, i64) {
        let a = a.rem_euclid(b);
        if a == 0 { return (0, b); }
        let mut s = b;
        let mut t = a;
        let mut m0 = 0;
        let mut m1 = 1;

        while t != 0 {
            let u = s / t;
            s -= t * u;
            m0 -= m1 * u;
            std::mem::swap(&mut s, &mut t);
            std::mem::swap(&mut m0, &mut m1);
        }

        if m0 < 0 { m0 += b / s; }
        (m0, s)
    }

    #[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
    #[repr(transparent)]
    pub struct ModInt { pub val: u32 }

    impl ModInt {
        #[inline(always)]
        pub fn modulus() -> u32 { crate::get_modulus() }
        pub fn new<I: RemEuclidU32>(val: I) -> Self { Self::raw(val.rem_euclid_u32(Self::modulus())) }
        #[inline]
        pub fn raw(val: u32) -> Self { Self { val } }
        pub fn inv(self) -> Self {
            let (x, gcd) = inv_gcd(self.val.into(), Self::modulus().into());
            if gcd != 1 { panic!("the multiplicative inverse {}^-1 mod {} does not exist", self.val, Self::modulus()) }
            Self::raw(x as u32)
        }
        pub fn pow(self, k: u64) -> Self {
            Self::raw(pow_mod_raw(self.val, k, Self::modulus()))
        }
        pub fn pow_vec(self, n: usize) -> Vec<Self> {
            let mut res = vec![Self::raw(0); n+1];
            res[0] += 1;
            for i in 1..=n {
                res[i] = res[i-1] * self;
            }
            res
        }
    }

    #[inline]
    pub fn mi<I: RemEuclidU32>(val: I) -> ModInt { ModInt::new(val) }

    impl<V: RemEuclidU32> From<V> for ModInt {
        #[inline]
        fn from(from: V) -> Self { Self::new(from) }
    }
    impl std::str::FromStr for ModInt {
        type Err = std::convert::Infallible;
        #[inline]
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            Ok(s.parse::<i64>()
            .map(Self::new)
            .unwrap_or_else(|_| todo!("parsing as an arbitrary precision integer?")))
        }
    }
    impl std::fmt::Display for ModInt {
        #[inline]
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            std::fmt::Display::fmt(&self.val, f)
        }
    }
    impl std::fmt::Debug for ModInt {
        #[inline]
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            std::fmt::Debug::fmt(&self.val, f)
        }
    }
    impl std::ops::Neg for ModInt {
        type Output = ModInt;

        #[inline]
        fn neg(self) -> Self::Output {
            //Self::raw(if self.val == 0 { 0 } else { Self::modulus() - self.val })
            Self::raw(norm(self.val.wrapping_neg(), Self::modulus()))
        }
    }

    impl std::ops::Add for ModInt {
        type Output = ModInt;
        #[inline]
        fn add(self, rhs: Self) -> Self::Output {
            Self::raw(add_mod_raw(self.val, rhs.val, Self::modulus()))
        }
    }
    impl std::ops::Sub for ModInt {
        type Output = ModInt;
        #[inline]
        fn sub(self, rhs: Self) -> Self::Output {
            Self::raw(sub_mod_raw(self.val, rhs.val, Self::modulus()))
        }
    }
    impl std::ops::Mul for ModInt {
        type Output = ModInt;
        #[inline]
        fn mul(self, rhs: Self) -> Self::Output {
            Self::raw(mul_mod_u32(self.val, rhs.val, Self::modulus()))
        }
    }
    impl std::ops::Div for ModInt {
        type Output = ModInt;
        #[inline]
        fn div(self, rhs: Self) -> Self::Output { self * rhs.inv() }
    }

    impl <I: RemEuclidU32> std::ops::Add<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn add(self, rhs: I) -> Self::Output { self + Self::new(rhs) }
    }
    impl <I: RemEuclidU32> std::ops::Sub<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn sub(self, rhs: I) -> Self::Output { self - Self::new(rhs) }
    }
    impl <I: RemEuclidU32> std::ops::Mul<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn mul(self, rhs: I) -> Self::Output { self * Self::new(rhs) }
    }
    impl <I: RemEuclidU32> std::ops::Div<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn div(self, rhs: I) -> Self::Output { self / Self::new(rhs) }
    }

    impl std::ops::AddAssign for ModInt {
        #[inline]
        fn add_assign(&mut self, rhs: Self) { *self = *self + rhs; }
    }
    impl std::ops::SubAssign for ModInt {
        #[inline]
        fn sub_assign(&mut self, rhs: Self) { *self = *self - rhs; }
    }
    impl std::ops::MulAssign for ModInt {
        #[inline]
        fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs; }
    }
    impl std::ops::DivAssign for ModInt {
        #[inline]
        fn div_assign(&mut self, rhs: Self) { *self = *self / rhs; }
    }
    impl <I: RemEuclidU32> std::ops::AddAssign<I> for ModInt {
        #[inline]
        fn add_assign(&mut self, rhs: I) { *self = *self + rhs; }
    }
    impl <I: RemEuclidU32> std::ops::SubAssign<I> for ModInt {
        #[inline]
        fn sub_assign(&mut self, rhs: I) { *self = *self - rhs; }
    }
    impl <I: RemEuclidU32> std::ops::MulAssign<I> for ModInt {
        #[inline]
        fn mul_assign(&mut self, rhs: I) { *self = *self * rhs; }
    }
    impl <I: RemEuclidU32> std::ops::DivAssign<I> for ModInt {
        #[inline]
        fn div_assign(&mut self, rhs: I) { *self = *self / rhs; }
    }

    impl std::iter::Sum for ModInt {
        #[inline]
        fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(Self::raw(0), std::ops::Add::add)
        }
    }
    impl std::iter::Product for ModInt {
        #[inline]
        fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(1.into(), std::ops::Mul::mul)
        }
    }
}

// const MODULUS: u32 = 998_244_353;
// //const MODULUS: u32 = 1_000_000_007;
// #[inline(always)]
// fn get_modulus() -> u32 { MODULUS }

static mut MODULUS: u32 = 998244353;
#[inline] fn get_modulus() -> u32 { unsafe { MODULUS } }
#[inline] fn set_modulus(value: u32) { unsafe { MODULUS = value; } }

use crate::modint::*;

#[allow(non_snake_case, unused_macros)]
fn main() -> Result<(), Box<dyn Error>> {
    let mut INPUT = std::io::stdin();
    let OUTPUT = std::io::stdout();

    let mut inp = Scanner::new(&mut INPUT);
    let mut out = BufWriter::with_capacity(IO_BUF_SIZE, OUTPUT);

    macro_rules! inp {
        () => { inp.read(); };
        ($t: ty) => { inp.read::<$t>(); };
        ($t: ty, $($tt: ty),*) => { (inp.read::<$t>(), $(inp.read::<$tt>(),)*); };
        [$t: ty; $n: expr] => { inp.vec::<$t>($n); };
    }
    macro_rules! println {
        () => { writeln!(out).unwrap(); };
        ($exp: expr) => { writeln!(out, "{}", $exp).unwrap(); };
        ($fmt: expr, $($arg : tt )*) => { writeln!(out, $fmt, $($arg)*).unwrap(); }
    }
    macro_rules! print {
        ($exp: expr) => { write!(out, "{}", $exp).unwrap(); };
        ($fmt: expr, $($arg : tt )*) => { write!(out, $fmt, $($arg)*).unwrap(); }
    }

    { // solution start
        let num_cases = 1;//inp!(usize);

        for _case_num in 1..=num_cases {
            let n = inp!(usize);
            set_modulus(inp!());

            let mut dp = vec![mi(0); n+1];
            dp[1] = mi(1);
            dp[2] = mi(2);
            for i in 2..n {
                let d = dp[i];
                dp[i+1] += d + d + 1;
                let d = d - dp[i-1];
                for j in (i*2..=n).step_by(i) {
                    dp[j] += d;
                }
            }

            let ans = dp[n];
            println!(ans);
        }
    } // solution end

    out.flush()?;
    Ok(())
}


use std::{cell::{Cell, RefCell, UnsafeCell}, cmp::{Reverse, max, min}, collections::{BTreeMap, BinaryHeap, HashMap, HashSet}, error::Error, fmt::Display, hash::{Hash, Hasher}, io::{BufWriter, Read, Stdin, Stdout, Write}, iter::Peekable, mem::swap, ops::{Not, Sub}, process::exit, rc::Rc, str::{FromStr, from_utf8, from_utf8_unchecked}};

const IO_BUF_SIZE: usize = 1 << 16;
type Input = Scanner<Stdin>;
type Output = BufWriter<Stdout>;
fn _init_input() -> Input { Scanner::new(std::io::stdin()) }
fn _init_output() -> Output { BufWriter::with_capacity(IO_BUF_SIZE, std::io::stdout()) }

#[repr(transparent)] struct Unsync<T>(T);
unsafe impl<T> Sync for Unsync<T> {}

type BadLazy<T> = Unsync<UnsafeCell<Option<T>>>;
impl<T> BadLazy<T> {
    const fn new() -> Self { Self(UnsafeCell::new(None)) }
}

static INPUT: BadLazy<Input> = BadLazy::new();
static OUTPUT: BadLazy<Output> = BadLazy::new();

fn inp<F: FnOnce(&mut Input) -> R, R>(f: F) -> R {
    unsafe { f((&mut *INPUT.0.get()).get_or_insert_with(_init_input)) }
}
fn out<F: FnOnce(&mut Output) -> R, R>(f: F) -> R {
    unsafe { f((&mut *OUTPUT.0.get()).get_or_insert_with(_init_output)) }
}

macro_rules! read {
    () => { read(); };
    ($t: ty) => { read::<$t>(); };
    ($t: ty, $($tt: ty),*) => { (read::<$t>(), $(read::<$t>(),)*); };
    [$t: ty; $n: expr] => { read_vec::<$t>($n); };
}
macro_rules! println {
    () => { out(|x| writeln!(x).unwrap()); };
    ($exp: expr) => { out(|x| writeln!(x, "{}", $exp).unwrap()); };
    ($fmt: expr, $($arg : tt )*) => { out(|x| writeln!(x, $fmt, $($arg)*).unwrap()); }
}
macro_rules! print {
    ($exp: expr) => { out(|x| write!(x, "{}", $exp).unwrap()); };
    ($fmt: expr, $($arg : tt )*) => { out(|x| write!(x, $fmt, $($arg)*).unwrap()); }
}

fn out_flush() { out(|x| x.flush().unwrap()); }

fn input_is_eof() -> bool { inp(|x| x.eof()) }
fn read_byte() -> u8 { inp(|x| x.byte()) }
fn read_bytes_no_skip(n: usize) -> Vec<u8> { inp(|x| x.bytes_no_skip(n)) }
fn read_bytes(n: usize) -> Vec<u8> { inp(|x| x.bytes(n)) }
fn read_bytes2(n: usize, m: usize) -> Vec<Vec<u8>> { inp(|x| x.bytes2(n, m)) }
fn read_token() -> Vec<u8> { inp(|x| x.token_bytes()) }
fn read_token_str() -> String { unsafe { String::from_utf8_unchecked(read_token()) } }
fn read_line() -> Vec<u8> { inp(|x| x.line_bytes()) }
fn read_line_str() -> String { unsafe { String::from_utf8_unchecked(read_line()) } }
fn read<T: FromStr>() -> T { read_token_str().parse::<T>().ok().unwrap() }
fn read_vec<T: FromStr>(n: usize) -> Vec<T> { (0..n).map(|_| read()).collect() }
fn read_vec2<T: FromStr>(n: usize, m: usize) -> Vec<Vec<T>> { (0..n).map(|_| read_vec(m)).collect() }

struct Scanner<R: Read> {
    src: R,
    _buf: Vec<u8>,
    _pt: usize, // pointer
    _rd: usize, // bytes read
}

#[allow(dead_code)]
impl<R: Read> Scanner<R> {
    fn new(src: R) -> Scanner<R> {
        Scanner { src, _buf: vec![0; IO_BUF_SIZE], _pt: 1, _rd: 1 }
    }

    fn _check_buf(&mut self) {
        if self._pt == self._rd {
            self._rd = self.src.read(&mut self._buf).unwrap_or(0);
            self._pt = (self._rd == 0) as usize;
        }
    }

    // returns true if end of file
    fn eof(&mut self) -> bool {
        self._check_buf();
        self._rd == 0
    }

    // filters \r, returns \0 if eof
    fn byte(&mut self) -> u8 {
        loop {
            self._check_buf();
            if self._rd == 0 { return 0; }
            let res = self._buf[self._pt];
            self._pt += 1;
            if res != b'\r' { return res; }
        }
    }

    fn bytes_no_skip(&mut self, n: usize) -> Vec<u8> { (0..n).map(|_| self.byte()).collect() }
    fn bytes(&mut self, n: usize) -> Vec<u8> {
        let res = self.bytes_no_skip(n);
        self.byte();
        res
    }
    fn bytes2(&mut self, n: usize, m: usize) -> Vec<Vec<u8>> { (0..n).map(|_| self.bytes(m)).collect() }

    fn token_bytes(&mut self) -> Vec<u8> {
        let mut res = Vec::new();
        let mut c = self.byte();
        while c <= b' ' {
            if c == b'\0' { return res; }
            c = self.byte();
        }
        loop {
            res.push(c);
            c = self.byte();
            if c <= b' ' { return res; }
        }
    }

    fn line_bytes(&mut self) -> Vec<u8> {
        let mut res = Vec::new();
        let mut c = self.byte();
        while c != b'\n' && c != b'\0' {
            res.push(c);
            c = self.byte();
        }
        res
    }
}
trait JoinToStr {
    fn join_to_str(&mut self, sep: &str) -> String;
    fn concat_to_str(&mut self) -> String;
}
impl<T: ToString, I: Iterator<Item = T>> JoinToStr for I {
    fn join_to_str(&mut self, sep: &str) -> String {
        let mut res = String::new();
        match self.next() {
            None => res,
            Some(first) => {
                res.push_str(&first.to_string());
                loop {
                    match self.next() {
                        None => break,
                        Some(item) => {
                            res.push_str(sep);
                            res.push_str(&item.to_string())
                        }
                    }
                }
                res
            }
        }
    }

    fn concat_to_str(&mut self) -> String {
        let mut res = String::new();
        for item in self { res.push_str(&item.to_string()); }
        res
    }
}

macro_rules! veci {
    ($n:expr , $i:ident : $gen:expr) => {{
        let n = $n;
        let mut list = Vec::with_capacity(n);
        for $i in 0..n {
            list.push($gen);
        }
        list
    }};
    ($n:expr , $gen:expr) => { veci!($n, __: $gen); }
}

fn abs_diff<T: Sub<Output = T> + PartialOrd>(x: T, y: T) -> T {
    if x < y { y - x } else { x - y }
}

// * end commons * //

mod modint {

    use std::{convert::Infallible, iter::Sum, mem::swap, ops::AddAssign};

    pub trait RemEuclidU32: Copy {
        /// Calculates `self` _mod_ `modulus` losslessly.
        fn rem_euclid_u32(self, modulus: u32) -> u32;

        fn pow_mod(self, exponent: u64, modulus: u32) -> u32 {
            pow_mod_raw(self.rem_euclid_u32(modulus), exponent, modulus)
        }
        fn mul_mod<Rhs: RemEuclidU32>(self, rhs: Rhs, modulus: u32) -> u32 {
            mul_mod_u32(self.rem_euclid_u32(modulus), rhs.rem_euclid_u32(modulus), modulus)
        }

        fn mod_pow_vec(self, n: usize, modulus: u32) -> Vec<u32> {
            let a = self.rem_euclid_u32(modulus);
            let mut res = vec![0u32; n+1];
            if modulus == 1 { return res; }
            res[0] = 1;
            for i in 1..=n {
                res[i] = mul_mod_u32(a, res[i-1], modulus);
            }
            res
        }
    }

    macro_rules! impl_rem_euclid_u32_for_small_signed {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        (self as i64).rem_euclid(i64::from(modulus)) as _
                    }
                }
            )*
        }
    }

    impl_rem_euclid_u32_for_small_signed!(i8, i16, i32, i64, isize);

    impl RemEuclidU32 for i128 {
        #[inline]
        fn rem_euclid_u32(self, modulus: u32) -> u32 {
            self.rem_euclid(i128::from(modulus)) as _
        }
    }

    macro_rules! impl_rem_euclid_u32_for_small_unsigned {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        self as u32 % modulus
                    }
                }
            )*
        }
    }

    macro_rules! impl_rem_euclid_u32_for_large_unsigned {
        ($($ty:tt),*) => {
            $(
                impl RemEuclidU32 for $ty {
                    #[inline]
                    fn rem_euclid_u32(self, modulus: u32) -> u32 {
                        (self % (modulus as $ty)) as _
                    }
                }
            )*
        }
    }

    impl_rem_euclid_u32_for_small_unsigned!(u8, u16, u32);
    impl_rem_euclid_u32_for_large_unsigned!(u64, u128);

    #[cfg(target_pointer_width = "32")]
    impl_rem_euclid_u32_for_small_unsigned!(usize);

    #[cfg(target_pointer_width = "64")]
    impl_rem_euclid_u32_for_large_unsigned!(usize);
    #[inline]
    pub fn mul_mod_u32(a: u32, b: u32, m: u32) -> u32 {
        ((a as u64) * (b as u64) % (m as u64)) as u32
    }

    // for a, b < m, undefined otherwise
    #[inline]
    pub fn add_mod_raw(a: u32, b: u32, m: u32) -> u32 {
        sub_mod_raw(a, m-b, m)
    }
    #[inline]
    pub fn sub_mod_raw(a: u32, b: u32, m: u32) -> u32 {
        let (r, c) = a.overflowing_sub(b);
        if c { r.wrapping_add(m) } else { r }
    }
    pub fn pow_mod_raw(a: u32, mut k: u64, m: u32) -> u32 {
        if m == 1 { return 0; }
        let mut a = a as u64;
        let m = m as u64;
        let mut r: u64 = 1;
        while k > 0 {
            if k & 1 == 1 {
                r = r * a % m;
            }
            k >>= 1;
            a = a * a % m;
        }
        return r as u32;
    }

    /// # Parameters
    /// * `b` `1 <= b`
    /// # Returns
    /// (x, g) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
    pub fn inv_gcd(a: i64, b: i64) -> (i64, i64) {
        let a = a.rem_euclid(b);
        if a == 0 { return (0, b); }
        let mut s = b;
        let mut t = a;
        let mut m0 = 0;
        let mut m1 = 1;

        while t != 0 {
            let u = s / t;
            s -= t * u;
            m0 -= m1 * u;
            std::mem::swap(&mut s, &mut t);
            std::mem::swap(&mut m0, &mut m1);
        }

        if m0 < 0 { m0 += b / s; }
        (m0, s)
    }

    #[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
    #[repr(transparent)]
    pub struct ModInt { pub val: u32 }

    impl ModInt {
        #[inline(always)]
        pub fn modulus() -> u32 { crate::get_modulus() }
        pub fn new<I: RemEuclidU32>(val: I) -> Self { Self::raw(val.rem_euclid_u32(Self::modulus())) }
        #[inline]
        pub fn raw(val: u32) -> Self { Self { val } }
        pub fn inv(self) -> Self {
            let (x, gcd) = inv_gcd(self.val.into(), Self::modulus().into());
            if gcd != 1 { panic!("the multiplicative inverse {}^-1 mod {} does not exist", self.val, Self::modulus()) }
            Self::raw(x as u32)
        }
        pub fn pow(self, k: u64) -> Self {
            Self::raw(pow_mod_raw(self.val, k, Self::modulus()))
        }
        pub fn pow_vec(self, n: usize) -> Vec<Self> {
            let mut res = vec![Self::raw(0); n+1];
            res[0] += 1;
            for i in 1..=n {
                res[i] = res[i-1] * self;
            }
            res
        }
    }

    #[inline]
    pub fn mi<I: RemEuclidU32>(val: I) -> ModInt { ModInt::new(val) }

    impl<V: RemEuclidU32> From<V> for ModInt {
        #[inline]
        fn from(from: V) -> Self { Self::new(from) }
    }
    impl std::str::FromStr for ModInt {
        type Err = std::convert::Infallible;
        #[inline]
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            Ok(s.parse::<i64>()
            .map(Self::new)
            .unwrap_or_else(|_| todo!("parsing as an arbitrary precision integer?")))
        }
    }
    impl std::fmt::Display for ModInt {
        #[inline]
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            std::fmt::Display::fmt(&self.val, f)
        }
    }
    impl std::fmt::Debug for ModInt {
        #[inline]
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            std::fmt::Debug::fmt(&self.val, f)
        }
    }
    impl std::ops::Neg for ModInt {
        type Output = ModInt;

        #[inline]
        fn neg(self) -> Self::Output {
            Self::raw(0) - self
            //Self::raw(norm(self.val.wrapping_neg(), Self::modulus()))
        }
    }

    impl std::ops::Add for ModInt {
        type Output = ModInt;
        #[inline]
        fn add(self, rhs: Self) -> Self::Output {
            Self::raw(add_mod_raw(self.val, rhs.val, Self::modulus()))
        }
    }
    impl std::ops::Sub for ModInt {
        type Output = ModInt;
        #[inline]
        fn sub(self, rhs: Self) -> Self::Output {
            Self::raw(sub_mod_raw(self.val, rhs.val, Self::modulus()))
        }
    }
    impl std::ops::Mul for ModInt {
        type Output = ModInt;
        #[inline]
        fn mul(self, rhs: Self) -> Self::Output {
            Self::raw(mul_mod_u32(self.val, rhs.val, Self::modulus()))
        }
    }
    impl std::ops::Div for ModInt {
        type Output = ModInt;
        #[inline]
        fn div(self, rhs: Self) -> Self::Output { self * rhs.inv() }
    }

    impl <I: RemEuclidU32> std::ops::Add<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn add(self, rhs: I) -> Self::Output { self + Self::new(rhs) }
    }
    impl <I: RemEuclidU32> std::ops::Sub<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn sub(self, rhs: I) -> Self::Output { self - Self::new(rhs) }
    }
    impl <I: RemEuclidU32> std::ops::Mul<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn mul(self, rhs: I) -> Self::Output { self * Self::new(rhs) }
    }
    impl <I: RemEuclidU32> std::ops::Div<I> for ModInt {
        type Output = ModInt;
        #[inline]
        fn div(self, rhs: I) -> Self::Output { self / Self::new(rhs) }
    }

    impl std::ops::AddAssign for ModInt {
        #[inline]
        fn add_assign(&mut self, rhs: Self) { *self = *self + rhs; }
    }
    impl std::ops::SubAssign for ModInt {
        #[inline]
        fn sub_assign(&mut self, rhs: Self) { *self = *self - rhs; }
    }
    impl std::ops::MulAssign for ModInt {
        #[inline]
        fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs; }
    }
    impl std::ops::DivAssign for ModInt {
        #[inline]
        fn div_assign(&mut self, rhs: Self) { *self = *self / rhs; }
    }
    impl <I: RemEuclidU32> std::ops::AddAssign<I> for ModInt {
        #[inline]
        fn add_assign(&mut self, rhs: I) { *self = *self + rhs; }
    }
    impl <I: RemEuclidU32> std::ops::SubAssign<I> for ModInt {
        #[inline]
        fn sub_assign(&mut self, rhs: I) { *self = *self - rhs; }
    }
    impl <I: RemEuclidU32> std::ops::MulAssign<I> for ModInt {
        #[inline]
        fn mul_assign(&mut self, rhs: I) { *self = *self * rhs; }
    }
    impl <I: RemEuclidU32> std::ops::DivAssign<I> for ModInt {
        #[inline]
        fn div_assign(&mut self, rhs: I) { *self = *self / rhs; }
    }

    impl std::iter::Sum for ModInt {
        #[inline] fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(Self::raw(0), std::ops::Add::add)
        }
    }
    impl std::iter::Product for ModInt {
        #[inline] fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
            iter.fold(1.into(), std::ops::Mul::mul)
        }
    }
    impl<'a> std::iter::Sum<&'a Self> for ModInt {
        #[inline] fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> ModInt {
            iter.fold(Self::raw(0), |a, &b| a + b)
        }
    }
    impl<'a> std::iter::Product<&'a Self> for ModInt {
        #[inline] fn product<I: Iterator<Item = &'a Self>>(iter: I) -> ModInt {
            iter.fold(1.into(), |a, &b| a * b)
        }
    }
}

// const MODULUS: u32 = 998_244_353;
// //const MODULUS: u32 = 1_000_000_007;
// #[inline(always)]
// fn get_modulus() -> u32 { MODULUS }

static MODULUS: Unsync<Cell<u32>> = Unsync(Cell::new(0));
#[inline] fn get_modulus() -> u32 { MODULUS.0.get() }
#[inline] fn set_modulus(value: u32) { MODULUS.0.set(value) }

use crate::modint::*;

#[allow(non_snake_case, unused_macros)]
fn main() -> Result<(), Box<dyn Error>> {
    let num_cases = 1;//read!(i32);

    for _case_num in 1..=num_cases {
        let n = read!(usize);
        set_modulus(read!());

        let mut dp = vec![mi(0); n+1];
        dp[1] = mi(1);
        dp[2] = mi(2);
        for i in 2..n {
            let d = dp[i];
            dp[i+1] += d + d + 1;
            let d = d - dp[i-1];
            for j in (i*2..=n).step_by(i) {
                dp[j] += d;
            }
        }

        let ans = dp[n];
        println!(ans); //
    }

    out_flush();
    Ok(())
}


fn main() {
    let (r, w) = (std::io::stdin(), std::io::stdout());
    let mut sc = IO::new(r.lock(), w.lock());

    let n: usize = sc.read();
    let m: i64 = sc.read();
    let mut dp = vec![0; n + 1];
    dp[n] = 1;
    let mut sum = vec![0; n + 2];
    sum[n] = sum[n + 1] + dp[n];

    for i in (1..n).rev() {
        dp[i] += sum[i + 1] - sum[n + 1];
        dp[i] %= m;

        for z in 2.. {
            let from = i * z;
            if from > n {
                break;
            }
            let to = from + z;
            dp[i] += sum[from] - sum[to.min(n + 1)];
            dp[i] %= m;
        }

        sum[i] = sum[i + 1] + dp[i];
        sum[i] %= m;
    }
    println!("{}", dp[1]);
}

pub struct IO<R, W: std::io::Write>(R, std::io::BufWriter<W>);

impl<R: std::io::Read, W: std::io::Write> IO<R, W> {
    pub fn new(r: R, w: W) -> IO<R, W> {
        IO(r, std::io::BufWriter::new(w))
    }
    pub fn write<S: ToString>(&mut self, s: S) {
        use std::io::Write;
        self.1.write_all(s.to_string().as_bytes()).unwrap();
    }
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .0
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r' || b == b'\t')
            .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r' && b != b'\t')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn usize0(&mut self) -> usize {
        self.read::<usize>() - 1
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}


// ---------- begin ModInt ----------
mod modint {

    #[allow(dead_code)]
    pub struct Mod;
    impl ConstantModulo for Mod {
        const MOD: u32 = 1_000_000_007;
    }

    #[allow(dead_code)]
    pub struct StaticMod;
    static mut STATIC_MOD: u32 = 0;
    impl Modulo for StaticMod {
        fn modulo() -> u32 {
            unsafe { STATIC_MOD }
        }
    }

    #[allow(dead_code)]
    impl StaticMod {
        pub fn set_modulo(p: u32) {
            unsafe {
                STATIC_MOD = p;
            }
        }
    }

    use std::marker::*;
    use std::ops::*;

    pub trait Modulo {
        fn modulo() -> u32;
    }

    pub trait ConstantModulo {
        const MOD: u32;
    }

    impl<T> Modulo for T
    where
        T: ConstantModulo,
    {
        fn modulo() -> u32 {
            T::MOD
        }
    }

    pub struct ModInt<T>(pub u32, PhantomData<T>);

    impl<T> Clone for ModInt<T> {
        fn clone(&self) -> Self {
            ModInt::new_unchecked(self.0)
        }
    }

    impl<T> Copy for ModInt<T> {}

    impl<T: Modulo> Add for ModInt<T> {
        type Output = ModInt<T>;
        fn add(self, rhs: Self) -> Self::Output {
            let mut d = self.0 + rhs.0;
            if d >= T::modulo() {
                d -= T::modulo();
            }
            ModInt::new_unchecked(d)
        }
    }

    impl<T: Modulo> AddAssign for ModInt<T> {
        fn add_assign(&mut self, rhs: Self) {
            *self = *self + rhs;
        }
    }

    impl<T: Modulo> Sub for ModInt<T> {
        type Output = ModInt<T>;
        fn sub(self, rhs: Self) -> Self::Output {
            let mut d = self.0 - rhs.0;
            if d >= T::modulo() {
                d += T::modulo();
            }
            ModInt::new_unchecked(d)
        }
    }

    impl<T: Modulo> SubAssign for ModInt<T> {
        fn sub_assign(&mut self, rhs: Self) {
            *self = *self - rhs;
        }
    }

    impl<T: Modulo> Mul for ModInt<T> {
        type Output = ModInt<T>;
        fn mul(self, rhs: Self) -> Self::Output {
            let v = self.0 as u64 * rhs.0 as u64 % T::modulo() as u64;
            ModInt::new_unchecked(v as u32)
        }
    }

    impl<T: Modulo> MulAssign for ModInt<T> {
        fn mul_assign(&mut self, rhs: Self) {
            *self = *self * rhs;
        }
    }

    impl<T: Modulo> Neg for ModInt<T> {
        type Output = ModInt<T>;
        fn neg(self) -> Self::Output {
            if self.0 == 0 {
                Self::zero()
            } else {
                Self::new_unchecked(T::modulo() - self.0)
            }
        }
    }

    impl<T> std::fmt::Display for ModInt<T> {
        fn fmt<'a>(&self, f: &mut std::fmt::Formatter<'a>) -> std::fmt::Result {
            write!(f, "{}", self.0)
        }
    }

    impl<T> std::fmt::Debug for ModInt<T> {
        fn fmt<'a>(&self, f: &mut std::fmt::Formatter<'a>) -> std::fmt::Result {
            write!(f, "{}", self.0)
        }
    }

    impl<T: Modulo> std::str::FromStr for ModInt<T> {
        type Err = std::num::ParseIntError;
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            let val = s.parse::<u32>()?;
            Ok(ModInt::new(val))
        }
    }

    impl<T: Modulo> From<usize> for ModInt<T> {
        fn from(val: usize) -> ModInt<T> {
            ModInt::new_unchecked((val % T::modulo() as usize) as u32)
        }
    }

    impl<T: Modulo> From<u64> for ModInt<T> {
        fn from(val: u64) -> ModInt<T> {
            ModInt::new_unchecked((val % T::modulo() as u64) as u32)
        }
    }

    impl<T: Modulo> From<i64> for ModInt<T> {
        fn from(val: i64) -> ModInt<T> {
            let m = T::modulo() as i64;
            ModInt::new((val % m + m) as u32)
        }
    }

    #[allow(dead_code)]
    impl<T> ModInt<T> {
        pub fn new_unchecked(d: u32) -> Self {
            ModInt(d, PhantomData)
        }
        pub fn zero() -> Self {
            ModInt::new_unchecked(0)
        }
        pub fn one() -> Self {
            ModInt::new_unchecked(1)
        }
        pub fn is_zero(&self) -> bool {
            self.0 == 0
        }
    }

    #[allow(dead_code)]
    impl<T: Modulo> ModInt<T> {
        pub fn new(d: u32) -> Self {
            ModInt::new_unchecked(d % T::modulo())
        }
        pub fn pow(&self, mut n: u64) -> Self {
            let mut t = Self::one();
            let mut s = *self;
            while n > 0 {
                if n & 1 == 1 {
                    t *= s;
                }
                s *= s;
                n >>= 1;
            }
            t
        }
        pub fn inv(&self) -> Self {
            assert!(self.0 != 0);
            self.pow(T::modulo() as u64 - 2)
        }
    }
}
// ---------- end ModInt ----------

use modint::*;
type M = ModInt<StaticMod>;

// ---------- begin input macro ----------
// reference: https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};
    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };
    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };
    ($iter:expr, bytes) => {
        read_value!($iter, String).bytes().collect::<Vec<u8>>()
    };
    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };
    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}
// ---------- end input macro ----------

fn naive() {
    input! {
        n: usize,
        m: u32,
    }
    StaticMod::set_modulo(m);
    let mut dp = vec![M::zero(); n + 1];
    dp[n] = M::one();
    for i in (1..n).rev() {
        let mut v = dp[i + 1];
        for x in (2..).map(|p| p * i).take_while(|x| *x <= n) {
            v += dp[x];
        }
        for x in (2..).map(|p| p * (i + 1)).take_while(|x| *x <= n) {
            v -= dp[x];
        }
        dp[i] = v + dp[i + 1];
    }
    println!("{:?}", dp[1] - dp[2]);
}

fn main() {
    naive();
}


use std::error::Error;
use std::io;
use std::cmp;

fn main() {
    if let Err(e) = run() {
        println!("{}", e);
    }
}

fn run() -> Result<(), Box<Error>> {
    io::stdin().read_line(&mut String::new());
    let mut s = String::new();
    io::stdin().read_line(&mut s);
    let mut v = 0;
    let mut max_v = 0;
    for b in s.trim().as_bytes() {
        match *b {
            65...90 => v += 1,
            32  => {
                max_v = cmp::max(max_v, v);
                v = 0;
            },
            _ => (),
        }
    }
    println!("{}", cmp::max(max_v, v));
    Ok(())
}


use std::io::*;

fn read<T: std::str::FromStr>(i: &mut StdinLock) -> T {
    let mut s = String::new();
    i.by_ref().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn volume_of(word: &str) -> usize {
    word.chars().filter(|x| x.is_uppercase()).count()
}

fn main() {
    // initialize stdin
    let sin = std::io::stdin();
    let mut sin = sin.lock();
    let sin = &mut sin;

    let _n: usize = read(sin);
    let s: String = read(sin);

    println!("{}", s.split(" ").map(|x| volume_of(x)).max().unwrap_or(0));
}


//! http://codeforces.com/problemset/problem/837/A

#[macro_export]
macro_rules! scanln {
  ($($var:ident : $ty:path),+) => {
    $(let $var: $ty;)+
    {
      use std::io;
      let mut __buf = String::new();
      io::stdin().read_line(&mut __buf).unwrap();
      let mut eles = __buf.split_whitespace();
      $($var = Scan::scan(&mut eles);)+
    }
  }
}

pub trait Scan {
  fn scan<'a, I>(eles: &mut I) -> Self where I: Iterator<Item=&'a str>;
}

macro_rules! impl_scan_single {
  ($ty:ty) => {
    impl Scan for $ty {
      fn scan<'a, I>(eles: &mut I) -> Self where I: Iterator<Item=&'a str> {
        let next = eles.next().unwrap();
        match next.parse() {
          Ok(res) => res,
          Err(_) => panic!()
        }
      }
    }
  }
}

impl_scan_single!(u8);
impl_scan_single!(u16);
impl_scan_single!(u32);
impl_scan_single!(u64);
impl_scan_single!(usize);
impl_scan_single!(i8);
impl_scan_single!(i16);
impl_scan_single!(i32);
impl_scan_single!(i64);
impl_scan_single!(isize);
impl_scan_single!(f32);
impl_scan_single!(f64);
impl_scan_single!(String);

const __IMPL_SCAN_FOR_VEC: () = {
  use std::str::FromStr;
  impl<T> Scan for Vec<T> where T: FromStr {
    fn scan<'a, I>(eles: &mut I) -> Self where I: Iterator<Item=&'a str> {
      eles.map(|str| match str.parse() {
        Ok(res) => res,
        Err(_) => panic!()
      }).collect()
    }
  }
};

pub trait CharExt: Copy {
  fn is_digit(self, radix: u32) -> bool;
  fn to_digit(self, radix: u32) -> Option<u32>;
  fn is_alphabetic(self) -> bool;
  fn is_lowercase(self) -> bool;
  fn is_uppercase(self) -> bool;
  fn is_whitespace(self) -> bool;
  fn is_alphanumeric(self) -> bool;
  fn to_lowercase(self) -> Self;
  fn to_uppercase(self) -> Self;
}

macro_rules! impl_u8 {
  ($meth:ident($($arg:ident : $ty:ty),*) -> $ret:ty) => {
    fn $meth(self, $($arg : $ty),*) -> $ret {
      let c = self as char;
      c.$meth($($arg),*)
    }
  }
}

impl CharExt for u8 {
  impl_u8!(is_digit(radix: u32) -> bool);
  impl_u8!(to_digit(radix: u32) -> Option<u32>);
  impl_u8!(is_alphabetic() -> bool);
  impl_u8!(is_lowercase() -> bool);
  impl_u8!(is_uppercase() -> bool);
  impl_u8!(is_whitespace() -> bool);
  impl_u8!(is_alphanumeric() -> bool);
  fn to_lowercase(self) -> Self {
    let c = self as char;
    c.to_lowercase()
      .next()
      .map(|c| c as u8)
      .unwrap_or(self)
  }
  fn to_uppercase(self) -> Self {
    let c = self as char;
    c.to_uppercase()
      .next()
      .map(|c| c as u8)
      .unwrap_or(self)
  }
}

// -----------------------------------------------------------------------------

fn volume(word: &[u8]) -> u32 {
  word.iter()
    .filter_map(|&c| if c.is_uppercase() { Some(()) } else { None })
    .count()
    as u32
}

fn main() {
  use std::io::{self, Write, BufWriter};
  let __stdout = io::stdout();
  let mut __out = BufWriter::with_capacity(4096, __stdout.lock());

  macro_rules! put {
    ($fmt:expr) => { write!(__out, $fmt).unwrap(); };
    ($fmt:expr, $($arg:expr),+) => { write!(__out, $fmt, $($arg),+).unwrap(); }
  }
  macro_rules! putln {
    () => { writeln!(__out, "").unwrap(); };
    ($fmt:expr) => { writeln!(__out, $fmt).unwrap(); };
    ($fmt:expr, $($arg:expr),+) => { writeln!(__out, $fmt, $($arg),+).unwrap(); }
  }
  macro_rules! fflush {
    () => { __out.flush().unwrap(); }
  }

  scanln!(_n: u32);
  scanln!(s: Vec<String>);
  let mut max_volume = 0;
  for word in s {
    let vol = volume(word.as_bytes());
    max_volume = std::cmp::max(vol, max_volume);
  }
  println!("{}", max_volume);
}


fn read_string() -> String {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Failed");
    input
}

fn read_int() -> u64 {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Failed");
    let x = input.trim().parse::<u64>().unwrap();
    input.clear();
    x
}

fn main(){
    let i = read_int() + 2;
    let s = read_string().replace("\n", "").replace("\r", "");
    let vec: Vec<&str> = s.split("").collect();
    let caps = vec!["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
    let mut max = 0;
    let mut tmp = 0;
    for x in 0..i{
        for cap in 0..caps.len(){
            if vec[x as usize] == caps[cap as usize]{
                tmp = tmp + 1;
            }
        }
        if (vec[x as usize] == " ") || (vec[x as usize] == ""){
            if max < tmp{
                max = tmp;
            }
            tmp = 0;
        }
    }
    println!("{:?}", max);
}


fn main(){
    let cin = std::io::stdin();
    let mut s = String::new();
    cin.read_line(&mut s)
        .expect(" ");
    cin.read_line(&mut s)
        .expect(" ");
    let mut ans = 0;
    for sub in s.trim().split(" "){
        let mut ct = 0;
        for c in sub.chars(){
            if c >= 'A' && c <= 'Z' {
                ct += 1;
            }
        }
        if ct > ans {
            ans = ct;
        }
    }
    println!("{}",ans);
}


use std::io::stdin;

fn main() {
    let s = {
        let mut input = String::new();
        stdin().read_line(&mut input).unwrap();
        input.clear();
        stdin().read_line(&mut input).unwrap();
        input
    };

    let ans = s.split_whitespace().map(|w| {
        w.chars().filter(|c| c.is_uppercase()).count()
    }).max().unwrap();

    println!("{}", ans);
}


use std::io;

fn main() {
    let mut a = String::new();
    let mut b = String::new();
    let mut c = String::new();

    io::stdin()
        .read_line(&mut a)
        .unwrap();

    io::stdin()
        .read_line(&mut b)
        .unwrap();

    io::stdin()
        .read_line(&mut c)
        .unwrap();

    let a: i64 = a.trim().parse().unwrap();
    let b: i64 = b.trim().parse().unwrap();
    let c: i64 = c.trim().parse().unwrap();

    let mut maxima = 0;
    let uno = (a+b)*c;
    let dos = a*b+c;
    maxima = std::cmp::max(uno,dos);
    let tres = a+b*c;
    maxima = std::cmp::max(maxima,tres);
    let cuatro = a+b+c;
    maxima = std::cmp::max(maxima,cuatro);
    let cinco = a*b*c;
    maxima = std::cmp::max(maxima,cinco);
    let seis = a*(b+c);
    maxima = std::cmp::max(maxima,seis);

    println!("{}", maxima);
}


fn main() {
    let a: i32 = {
        let mut line = String::new();
        std::io::stdin().read_line(&mut line);
        line.trim().parse().unwrap()
    };
    let b: i32 = {
        let mut line = String::new();
        std::io::stdin().read_line(&mut line);
        line.trim().parse().unwrap()
    };
    let c: i32 = {
        let mut line = String::new();
        std::io::stdin().read_line(&mut line);
        line.trim().parse().unwrap()
    };

    let best = |a, b| std::cmp::max(a + b, a * b);
    let x = std::cmp::max(best(best(a, b), c), best(a, best(b, c)));
    println!("{:?}", x);
}


#[allow(unused)] use std::io::*;
#[allow(unused)] use std::collections::*;
#[allow(unused)] use std::mem::*;
#[allow(unused)] use std::num::*;
#[allow(unused)] use std::cmp::*;
#[allow(unused)] macro_rules! scan { ($($x:ty), +) => {{
    let mut inp = String::new(); stdin().read_line(&mut inp).ok();
    let s = inp.split(' ').map(|x| x.trim()).filter(|x| x.len() != 0).collect();
    let mut cnt : usize = 0;
    fn next<T>(cnt: &mut usize, p: &Vec<&str>) -> T where T:std::str::FromStr
    { *cnt += 1; p[*cnt-1].parse().ok().unwrap() }
    ($(next::<$x>(&mut cnt, &s)), +)
    }}; }
#[allow(unused)] macro_rules! arr { ($n:expr, $T:ty) => {{
    let mut inp = String::new(); stdin().read_line(&mut inp).ok();
    let mut s = inp.split(' ').map(|x| x.trim()).filter(|x| x.len() != 0);
    let mut v = Vec::new(); v.reserve(($n) as usize);
    for st in s { v.push(st.parse::<$T>().unwrap()); } v
    }}; }

///////////////////////////////////////////////////////////////////////////////
fn main()
{
    let a = scan!(i32);
    let b = scan!(i32);
    let c = scan!(i32);
    println!("{}", max(max(max(max(max(
        a + b + c,
        a * b * c),
        (a + b) * c),
        a + b * c),
        a * (b + c)),
        a * b + c));
}


use std::io;

fn main() {
    let mut a = String::new();
    let mut b = String::new();
    let mut c = String::new();

    io::stdin()
        .read_line(&mut a)
        .unwrap();

    io::stdin()
        .read_line(&mut b)
        .unwrap();

    io::stdin()
        .read_line(&mut c)
        .unwrap();

    let a: i64 = a.trim().parse().unwrap();
    let b: i64 = b.trim().parse().unwrap();
    let c: i64 = c.trim().parse().unwrap();

    println!("{}",
             [
        (a+b)*c,
        a*b+c,
        a+b*c,
        a+b+c,
        a*b*c,
        a*(b+c)
    ]
    .iter()
    .max()
    .unwrap()
    );
}


// use rand::Rng;

use std::collections::*;
use std::io;

fn trim_newline(s: &mut String) {
    if s.ends_with('\n') {
        s.pop();
        if s.ends_with('\r') {
            s.pop();
        }
    }
}
macro_rules! parse_input {
    ($t:ident) => {{
        let mut input_line = String::new();
        io::stdin().read_line(&mut input_line).unwrap();
        trim_newline(&mut input_line);
        input_line.parse::<$t>().unwrap()
    }};
}

macro_rules! split_input {
    ($t:ident) => {{
        parse_input!(String)
            .split(" ")
            .map(|z| z.parse::<$t>().unwrap())
            .collect::<Vec<$t>>()
    }};
}

fn main() {
    let mut a = parse_input!(usize);
    let mut b = parse_input!(usize);
    let mut c = parse_input!(usize);
    if a == 1 {
        b += 1;
    }
    if b == 1 {
        if c < a {
            c += 1;
        } else {
            a += 1;
        }
    }
    if c == 1 {
        b += 1;
    }

    println!("{}", a * b * c);
}


use std::io;

fn main() {
    let mut a = String::new();
    let mut b = String::new();
    let mut c = String::new();

    io::stdin().read_line(&mut a).unwrap();
    io::stdin().read_line(&mut b).unwrap();
    io::stdin().read_line(&mut c).unwrap();

    let a: u16 = a.trim().parse().unwrap();
    let b: u16 = b.trim().parse().unwrap();
    let c: u16 = c.trim().parse().unwrap();

    let mut max_value: u16 = 0;

    if (a + b + c) > max_value {
        max_value = a + b + c;
    }
    if (a * b * c) > max_value {
        max_value = a * b * c;
    }
    if (a * b + c) > max_value {
        max_value = a * b + c;
    }
    if (a + b * c) > max_value {
        max_value = a + b * c;
    }

    if ((a + b) * c) > max_value {
        max_value = (a + b) * c;
    }
    if (a * (b + c)) > max_value {
        max_value = a * (b + c);
    }

    if (a + (b * c)) > max_value {
        max_value = a + (b * c);
    }
    if ((a * b) + c) > max_value {
        max_value = (a * b) + c;
    }

    println!("{}", max_value);
}


// {{{ by shik

use std::io;

#[allow(dead_code)]
fn gets() -> String {
    let mut s = String::new();
    io::stdin().read_line(&mut s).unwrap();
    s.trim().to_string()
}

#[allow(unused_macros)]
macro_rules! R {
    ( $ty:ty, ... ) => {
        gets().split_whitespace().map(|x| x.parse::<$ty>().unwrap()).collect::<Vec<_>>()
    };
    ( $($ty:ty),* ) => {{
        let line = gets();
        let mut it = line.split_whitespace();
        ( $(it.next().unwrap().parse::<$ty>().unwrap(),)* )
    }}
}

#[allow(unused_macros)]
macro_rules! W {
    ( $x:expr ) => {{
        println!("{}", $x);
    }};
    ( $x:expr, $($xs:expr),* ) => {{
        print!("{} ", $x);
        W!($($xs),*);
    }}
}

#[allow(unused_macros)]
macro_rules! join {
    ($x:expr, $($xs:expr),*; $sep:expr) => { concat!($x, $($sep, $xs),*) }
}

#[allow(unused_macros)]
macro_rules! dump {
    ($($x:expr),*) => {
        eprintln!(join!($(concat!(stringify!($x), " = {:?}")),*; ", "), $($x),*);
    }
}

// }}}

use std::cmp;

fn main() {
    let (a, ) = R!(i32);
    let (b, ) = R!(i32);
    let (c, ) = R!(i32);
    println!("{}", vec![a+b+c, a+b*c, a*b+c, a*b*c, (a+b)*c, a*(b+c)].into_iter().fold(0, cmp::max));
}


use std::io::{self, Stdin};
use std::str::{self, FromStr};
use std::error::Error;
use std::thread;

fn exec() {
    let mut sc = Scanner::new();
    let n: i64 = sc.ne();
    let ans = if is_prime(n) {
        1
    } else if n & 1 == 0 || is_prime(n - 2) {
        2
    } else {
        3
    };
    println!("{}", ans);
}

fn is_prime(x: i64) -> bool {
    let mut y = 2;
    while y * y <= x {
        if x % y == 0 {
            return false;
        }
        y += 1;
    }
    x != 1
}
const DEFAULT_STACK: usize = 16 * 1024 * 1024;
fn main() {
    let builder = thread::Builder::new();
    let th = builder.stack_size(DEFAULT_STACK);
    let handle = th.spawn(|| { exec(); }).unwrap();
    let _ = handle.join();
}

#[allow(dead_code)]
struct Scanner {
    stdin: Stdin,
    id: usize,
    buf: Vec<u8>,
}

#[allow(dead_code)]
impl Scanner {
    fn new() -> Scanner {
        Scanner {
            stdin: io::stdin(),
            id: 0,
            buf: Vec::new(),
        }
    }
    fn next_line(&mut self) -> Option<String> {
        let mut res = String::new();
        match self.stdin.read_line(&mut res) {
            Ok(0) => return None,
            Ok(_) => Some(res),
            Err(why) => panic!("error in read_line: {}", why.description()),
        }
    }
    fn next<T: FromStr>(&mut self) -> Option<T> {
        while self.buf.len() == 0 {
            self.buf = match self.next_line() {
                Some(r) => {
                    self.id = 0;
                    r.trim().as_bytes().to_owned()
                }
                None => return None,
            };
        }
        let l = self.id;
        assert!(self.buf[l] != b' ');
        let n = self.buf.len();
        let mut r = l;
        while r < n && self.buf[r] != b' ' {
            r += 1;
        }
        let res = match str::from_utf8(&self.buf[l..r]).ok().unwrap().parse::<T>() {
            Ok(s) => Some(s),
            Err(_) => panic!("parse error"),
        };
        while r < n && self.buf[r] == b' ' {
            r += 1;
        }
        if r == n {
            self.buf.clear();
        } else {
            self.id = r;
        }
        res
    }
    fn ne<T: FromStr>(&mut self) -> T {
        self.next::<T>().unwrap()
    }
}


//https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8 より
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};
    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };
    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };
    ($iter:expr, bytes) => {
        read_value!($iter, String).bytes().collect::<Vec<u8>>()
    };
    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };
    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

//

fn is_prime(n: u64) -> bool {
    if n <= 1 {
        return false;
    }
    for k in (2..).take_while(|k| k * k <= n) {
        if n % k == 0 {
            return false;
        }
    }
    true
}

fn run() {
    input! {
        n: u64,
    }
    let ans = if is_prime(n) {
        1
    } else if n % 2 == 0 {
        2
    } else if is_prime(n - 2) {
        2
    } else {
        3
    };
    println!("{}", ans);
}

fn main() {
    run();
}


use std::io;

struct Prime {
    a: Vec<bool>,
    al: usize,
    t: Vec<usize>,
}

#[allow(dead_code)]
impl Prime {
    fn new(n: usize) -> Self {
        let mut t = vec![2; 1];
        let s = (n as f64).sqrt().round() as usize + 3;
        let mut a = vec![true; s];
        a[0] = false;
        a[1] = false;
        for i in (4..s).step_by(2) {
            a[i] = false;
        }
        for i in (3..s).step_by(2) {
            if !a[i] {
                continue;
            }
            t.push(i);
            if i * i < s {
                for j in ((i * i)..s).step_by(i * 2) {
                    a[j] = false;
                }
            }
        }
        let al = a.len();
        Prime { a, al, t }
    }

    fn is_prime(&self, x: usize) -> bool {
        if x < self.al {
            return self.a[x];
        }

        for c in self.t.iter() {
            if x % c == 0 {
                return false;
            }
        }

        true
    }
}

#[allow(dead_code)]
fn solve() -> Vec<String> {
    let mut input = "".split_ascii_whitespace();
    let mut read = || loop {
        if let Some(word) = input.next() {
            break word;
        }
        input = {
            let mut input = "".to_owned();
            io::stdin().read_line(&mut input).unwrap();
            if input.is_empty() {
                panic!("reached EOF");
            }
            Box::leak(input.into_boxed_str()).split_ascii_whitespace()
        };
    };
    macro_rules! read(($ty:ty) => (read().parse::<$ty>().unwrap()));

    let mut rr = vec!["".to_string(); 0];

    let t = 1;
    for _ in 0..t {
        let n = read!(usize);

        let mut r = 3;
        if n > 3 && n % 2 == 0 {
            r = 2;
        } else {
            let pr = Prime::new(n);
            if pr.is_prime(n) {
                r = 1;
            } else if pr.is_prime(n - 2) {
                r = 2;
            }
        }

        rr.push(format!("{}", r));
    }

    rr
}

#[allow(dead_code)]
fn main() {
    let output = solve();
    println!("{}", output.join("\n"));
}


fn main() {
    let mut input = String::new();

    std::io::stdin().read_line(&mut input).expect("Read to input failed!");

    let mut input = input.trim().split(' ');
    let mut base_number = input
                .next()
                .unwrap()
                .parse::<i32>()
                .expect("BASE_NUMBER::Parse to i32 failed!");

    let mut amount = input
        .next()
        .unwrap()
        .parse::<i32>()
        .expect("AMOUNT::Parse to i32 failed!");

    let mut result_number = i32::default();

    for i in (0..amount) {

        let mut last_digit = base_number % 10;

        if last_digit == 0 {
            base_number /= 10;
        }else {
            base_number -= 1;
        }

    }

    println!("{}", base_number);
}


struct Scan {
    buffer: std::collections::VecDeque<String>
}

impl Scan {
    fn new() -> Scan {
        Scan { buffer: std::collections::VecDeque::new() }
    }

    fn next<T: std::str::FromStr>(&mut self)-> T {
        loop {
            if let Some(token) = self.buffer.pop_front() {
                break token.parse::<T>().ok().unwrap();
            }
            let mut line = String::new();
            std::io::stdin().read_line(&mut line).expect("Fail to read");
            self.buffer = line.split_whitespace().map(String::from).collect();
        }
    }

}

fn _main() {
    let mut scan = Scan::new();
    let mut n: usize = scan.next();
    let k: usize = scan.next();
    for _ in 0..k {
        if n % 10 == 0 { n /= 10; }
        else           { n -= 1;  }
    }
    println!("{}", n);
}

fn main() {
    std::thread::Builder::new()
        .stack_size(1<<23).spawn(_main).unwrap().join().unwrap();
}


use std::io;

macro_rules! parse_line {
    ($($t: ty),+) => ({
        let mut a_str = String::new();
        io::stdin().read_line(&mut a_str).expect("read error");
        let mut a_iter = a_str.split_whitespace();
        (
            $(
            a_iter.next().unwrap().parse::<$t>().expect("parse error"),
            )+
        )
    })
}

fn parse_array() -> Vec<u64> {
    let mut a_str = String::new();
    io::stdin().read_line(&mut a_str).expect("read error");
    a_str
        .trim()
        .split(" ")
        .map(|x| x.parse::<u64>().expect("parse error"))
        .collect()
}

fn main() {
    let (mut n,k) = parse_line!(u128, u32);
    for _ in 0..k {
        if n % 10 == 0 {
            n/=10;
        }else{
            n-=1;
        }
    }
    println!("{}", n);
}


use std::io;

fn tanya(mut n: i64, k: i64) -> i64 {
    for _ in  0..k {
        if n % 10 == 0 {
            n /= 10;
        } else {
            n -= 1;
        }
    }
    n
}

fn main() -> io::Result<()> {
    let mut buffer = String::new();
    io::stdin().read_line(&mut buffer)?;
    let mut parts = buffer.split_whitespace().map(|s| s.parse::<i64>());
    match (parts.next(), parts.next()) {
        (Some(Ok(a)), Some(Ok(b))) => println!("{}", tanya(a,b)),
        _ =>  {},
    }
    Ok(())
}


use std::io::*;

fn main() {
    let mut line = String::new();
    stdin().read_line(&mut line).ok().expect("read error");
    line = line.trim().to_string();

    let split: Vec<&str> = line.trim().split_whitespace().collect();

    let mut n: i32 = split[0].parse().ok().unwrap();
    let mut k: i32 = split[1].parse().ok().unwrap();

    let output: i32 = subtract_number(n, k);
    println!("{}", output);
}

fn subtract_number(mut n: i32, mut k: i32) -> i32 {
    if k == 0 {
        return n
    }

    if n % 10 != 0 {
        return subtract_number(n - 1, k - 1)
    }
    return subtract_number(n / 10, k - 1)
}


use std::io;

fn main(){
    let mut buffer = String::new();
    io::stdin().read_line(&mut buffer).expect("Failed to read input");

    let mut iter = buffer.split_whitespace();
    let mut first_number: i32 = iter.next().unwrap()
        .trim().parse().unwrap();
    let second_number: i32 = iter.next().unwrap()
        .trim().parse().unwrap();

    for k in 0..second_number {
        if first_number % 10 == 0 {
            first_number = first_number / 10;
        } else {
            first_number = first_number - 1;
        }
    }

    println!("{}", first_number);
}


use std::io::stdin;
fn main() {
    let (n, k) = parse_arg();
    println!("{}", resolver(n, k));
}

fn parse_arg() -> (usize, usize) {
    let mut text = String::new();
    stdin().read_line(&mut text).expect("msg: &str");
    let v: Vec<&str> = text.trim().split_whitespace().collect();
    (
        v[0].parse().expect("msg: &str"),
        v[1].parse().expect("msg: &str"),
    )
}

fn resolver(n: usize, k: usize) -> usize {
    if k == 0 {
        return n;
    }
    if n % 10 == 0 {
        resolver(n / 10, k - 1)
    } else {
        resolver(n - 1, k - 1)
    }
}


use std::io::{BufWriter, stdin, stdout, Write};

struct Scanner {
    buffer: Vec<String>
}

impl Scanner {
    fn new() -> Scanner {
        Scanner {
            buffer: vec![]
        }
    }

    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed To Parse.");
            }

            let mut input = String::new();
            stdin().read_line(&mut input).expect("Failed To Read.");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

fn main() {
    let mut scanner = Scanner::new();
    let out = &mut BufWriter::new(stdout());
    let (mut n, mut k) = (scanner.next::<i64>(), scanner.next::<i64>());
    while k > 0 {
        if n % 10 != 0 {
            n -= 1;
        } else {
            n /= 10;
        }

        k -= 1;
    }

    writeln!(out, "{}", n).ok();
}


fn main() {
    let mut text = String::new();
    std::io::stdin().read_line(&mut text).expect("");
    let it : Vec<i32> = text.trim().split_whitespace().map(|x| x.parse::<i32>().expect("")).collect();
    let k = it[0];
    let n = it[1];
    let w = it[2];
    println!("{}", std::cmp::max((w + 1) * w / 2 * k - n, 0));
}


use std::io;
use std::io::prelude::*;
fn main() {
    let mut inputnum = String::new();
    io::stdin().read_line(&mut inputnum).expect("Error");
    let mut result : Vec<i64> = inputnum.split_whitespace().map(|x| x.parse::<i64>().unwrap()).collect();
    let totalcost:i64= (result[0]*(result[2]*(result[2]+1)))/2;
    if totalcost-result[1]>0{
        println!("{}",totalcost-result[1]);
    }
    else{
        println!("0");
    }
}


use std::io;

fn main() {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    let read_in = buf.split_whitespace().map(|c| c.trim().parse::<usize>().unwrap()).collect::<Vec<usize>>();
    let (k, n, w) = (read_in[0], read_in[1], read_in[2]);
    let cost = w * (w + 1) / 2 * k;
    let ret: usize;
    if cost <= n {
        ret = 0;
    } else {
        ret = cost - n;
    }
    println!("{}", ret);
}