//https://github.com/manta1130/competitive-template-rs

use input::*;

pub mod input {
    use std::cell::RefCell;
    use std::io;
    pub const SPLIT_DELIMITER: char = ' ';
    pub use std::io::prelude::*;

    #[macro_export]
    thread_local! {
        pub static INPUT_BUFFER:RefCell<std::collections::VecDeque<String>>=RefCell::new(std::collections::VecDeque::new());
    }

    #[macro_export]
    macro_rules! input_internal {
        ($x:ident : $t:ty) => {
            INPUT_BUFFER.with(|p| {
                if p.borrow().len() == 0 {
                    let temp_str = input_line_str();
                    let mut split_result_iter = temp_str
                        .split(SPLIT_DELIMITER)
                        .map(|q| q.to_string())
                        .collect::<std::collections::VecDeque<_>>();
                    p.borrow_mut().append(&mut split_result_iter)
                }
            });
            let mut buf_split_result = String::new();
            INPUT_BUFFER.with(|p| buf_split_result = p.borrow_mut().pop_front().unwrap());
            let $x: $t = buf_split_result.parse().unwrap();
        };
        (mut $x:ident : $t:ty) => {
            INPUT_BUFFER.with(|p| {
                if p.borrow().len() == 0 {
                    let temp_str = input_line_str();
                    let mut split_result_iter = temp_str
                        .split(SPLIT_DELIMITER)
                        .map(|q| q.to_string())
                        .collect::<std::collections::VecDeque<_>>();
                    p.borrow_mut().append(&mut split_result_iter)
                }
            });
            let mut buf_split_result = String::new();
            INPUT_BUFFER.with(|p| buf_split_result = p.borrow_mut().pop_front().unwrap());
            let mut $x: $t = buf_split_result.parse().unwrap();
        };
    }

    #[macro_export]
    macro_rules! inputv {
    ($i:ident : $t:ty) => {
        input_internal!{$i : $t}
    };
    (mut $i:ident : $t:ty) => {
        input_internal!{mut $i : $t}
    };
    ($i:ident : $t:ty $(,)*) => {
            input_internal!{$i : $t}
    };
    (mut $i:ident : $t:ty $(,)*) => {
            input_internal!{mut $i : $t}
    };
    (mut $i:ident : $t:ty,$($q:tt)*) => {
            input_internal!{mut $i : $t}
            inputv!{$($q)*}
    };
    ($i:ident : $t:ty,$($q:tt)*) => {
            input_internal!{$i : $t}
            inputv!{$($q)*}
    };
}

    pub fn input_all() {
        INPUT_BUFFER.with(|p| {
            if p.borrow().len() == 0 {
                let mut temp_str = String::new();
                std::io::stdin().read_to_string(&mut temp_str).unwrap();
                let mut split_result_iter = temp_str
                    .split_whitespace()
                    .map(|q| q.to_string())
                    .collect::<std::collections::VecDeque<_>>();
                p.borrow_mut().append(&mut split_result_iter)
            }
        });
    }

    pub fn input_line_str() -> String {
        let mut s = String::new();
        io::stdin().read_line(&mut s).unwrap();
        s.trim().to_string()
    }

    #[allow(clippy::match_wild_err_arm)]
    pub fn input_vector<T>() -> Vec<T>
    where
        T: std::str::FromStr,
    {
        let mut v: Vec<T> = Vec::new();

        let s = input_line_str();
        let split_result = s.split(SPLIT_DELIMITER);
        for z in split_result {
            let buf = match z.parse() {
                Ok(r) => r,
                Err(_) => panic!("Parse Error",),
            };
            v.push(buf);
        }
        v
    }

    #[allow(clippy::match_wild_err_arm)]
    pub fn input_vector_row<T>(n: usize) -> Vec<T>
    where
        T: std::str::FromStr,
    {
        let mut v = Vec::with_capacity(n);
        for _ in 0..n {
            let buf = match input_line_str().parse() {
                Ok(r) => r,
                Err(_) => panic!("Parse Error",),
            };
            v.push(buf);
        }
        v
    }

    pub trait ToCharVec {
        fn to_charvec(&self) -> Vec<char>;
    }

    impl ToCharVec for String {
        fn to_charvec(&self) -> Vec<char> {
            self.to_string().chars().collect::<Vec<_>>()
        }
    }
}

//https://github.com/rust-lang-ja/ac-library-rs
//https://github.com/manta1130/competitive-template-rs

use input::*;
use modint::*;

pub mod input {
    use std::cell::RefCell;
    use std::io;
    pub const SPLIT_DELIMITER: char = ' ';
    pub use std::io::prelude::*;

    #[macro_export]
    thread_local! {
        pub static INPUT_BUFFER:RefCell<std::collections::VecDeque<String>>=RefCell::new(std::collections::VecDeque::new());
    }

    #[macro_export]
    macro_rules! input_internal {
        ($x:ident : $t:ty) => {
            INPUT_BUFFER.with(|p| {
                if p.borrow().len() == 0 {
                    let temp_str = input_line_str();
                    let mut split_result_iter = temp_str
                        .split(SPLIT_DELIMITER)
                        .map(|q| q.to_string())
                        .collect::<std::collections::VecDeque<_>>();
                    p.borrow_mut().append(&mut split_result_iter)
                }
            });
            let mut buf_split_result = String::new();
            INPUT_BUFFER.with(|p| buf_split_result = p.borrow_mut().pop_front().unwrap());
            let $x: $t = buf_split_result.parse().unwrap();
        };
        (mut $x:ident : $t:ty) => {
            INPUT_BUFFER.with(|p| {
                if p.borrow().len() == 0 {
                    let temp_str = input_line_str();
                    let mut split_result_iter = temp_str
                        .split(SPLIT_DELIMITER)
                        .map(|q| q.to_string())
                        .collect::<std::collections::VecDeque<_>>();
                    p.borrow_mut().append(&mut split_result_iter)
                }
            });
            let mut buf_split_result = String::new();
            INPUT_BUFFER.with(|p| buf_split_result = p.borrow_mut().pop_front().unwrap());
            let mut $x: $t = buf_split_result.parse().unwrap();
        };
    }

    #[macro_export]
    macro_rules! inputv {
    ($i:ident : $t:ty) => {
        input_internal!{$i : $t}
    };
    (mut $i:ident : $t:ty) => {
        input_internal!{mut $i : $t}
    };
    ($i:ident : $t:ty $(,)*) => {
            input_internal!{$i : $t}
    };
    (mut $i:ident : $t:ty $(,)*) => {
            input_internal!{mut $i : $t}
    };
    (mut $i:ident : $t:ty,$($q:tt)*) => {
            input_internal!{mut $i : $t}
            inputv!{$($q)*}
    };
    ($i:ident : $t:ty,$($q:tt)*) => {
            input_internal!{$i : $t}
            inputv!{$($q)*}
    };
}

    pub fn input_all() {
        INPUT_BUFFER.with(|p| {
            if p.borrow().len() == 0 {
                let mut temp_str = String::new();
                std::io::stdin().read_to_string(&mut temp_str).unwrap();
                let mut split_result_iter = temp_str
                    .split_whitespace()
                    .map(|q| q.to_string())
                    .collect::<std::collections::VecDeque<_>>();
                p.borrow_mut().append(&mut split_result_iter)
            }
        });
    }

    pub fn input_line_str() -> String {
        let mut s = String::new();
        io::stdin().read_line(&mut s).unwrap();
        s.trim().to_string()
    }

    #[allow(clippy::match_wild_err_arm)]
    pub fn input_vector<T>() -> Vec<T>
    where
        T: std::str::FromStr,
    {
        let mut v: Vec<T> = Vec::new();

        let s = input_line_str();
        let split_result = s.split(SPLIT_DELIMITER);
        for z in split_result {
            let buf = match z.parse() {
                Ok(r) => r,
                Err(_) => panic!("Parse Error",),
            };
            v.push(buf);
        }
        v
    }

    #[allow(clippy::match_wild_err_arm)]
    pub fn input_vector_row<T>(n: usize) -> Vec<T>
    where
        T: std::str::FromStr,
    {
        let mut v = Vec::with_capacity(n);
        for _ in 0..n {
            let buf = match input_line_str().parse() {
                Ok(r) => r,
                Err(_) => panic!("Parse Error",),
            };
            v.push(buf);
        }
        v
    }

    pub trait ToCharVec {
        fn to_charvec(&self) -> Vec<char>;
    }

    impl ToCharVec for String {
        fn to_charvec(&self) -> Vec<char> {
            self.to_string().chars().collect::<Vec<_>>()
        }
    }
}
pub mod internal_math {
    #![allow(dead_code)]
    use std::mem::swap;

    /* const */
    pub(crate) fn safe_mod(mut x: i64, m: i64) -> i64 {
        x %= m;
        if x < 0 {
            x += m;
        }
        x
    }

    pub(crate) struct Barrett {
        pub(crate) _m: u32,
        pub(crate) im: u64,
    }

    impl Barrett {
        pub(crate) fn new(m: u32) -> Barrett {
            Barrett {
                _m: m,
                im: (-1i64 as u64 / m as u64).wrapping_add(1),
            }
        }

        pub(crate) fn umod(&self) -> u32 {
            self._m
        }

        #[allow(clippy::many_single_char_names)]
        pub(crate) fn mul(&self, a: u32, b: u32) -> u32 {
            mul_mod(a, b, self._m, self.im)
        }
    }

    #[allow(clippy::many_single_char_names)]
    pub(crate) fn mul_mod(a: u32, b: u32, m: u32, im: u64) -> u32 {
        let mut z = a as u64;
        z *= b as u64;
        let x = (((z as u128) * (im as u128)) >> 64) as u64;
        let mut v = z.wrapping_sub(x.wrapping_mul(m as u64)) as u32;
        if m <= v {
            v = v.wrapping_add(m);
        }
        v
    }

    /* const */
    #[allow(clippy::many_single_char_names)]
    pub(crate) fn pow_mod(x: i64, mut n: i64, m: i32) -> i64 {
        if m == 1 {
            return 0;
        }
        let _m = m as u32;
        let mut r: u64 = 1;
        let mut y: u64 = safe_mod(x, m as i64) as u64;
        while n != 0 {
            if (n & 1) > 0 {
                r = (r * y) % (_m as u64);
            }
            y = (y * y) % (_m as u64);
            n >>= 1;
        }
        r as i64
    }

    /* const */
    pub(crate) fn is_prime(n: i32) -> bool {
        let n = n as i64;
        match n {
            _ if n <= 1 => return false,
            2 | 7 | 61 => return true,
            _ if n % 2 == 0 => return false,
            _ => {}
        }
        let mut d = n - 1;
        while d % 2 == 0 {
            d /= 2;
        }
        for &a in &[2, 7, 61] {
            let mut t = d;
            let mut y = pow_mod(a, t, n as i32);
            while t != n - 1 && y != 1 && y != n - 1 {
                y = y * y % n;
                t <<= 1;
            }
            if y != n - 1 && t % 2 == 0 {
                return false;
            }
        }
        true
    }

    /* const */
    #[allow(clippy::many_single_char_names)]
    pub(crate) fn inv_gcd(a: i64, b: i64) -> (i64, i64) {
        let a = safe_mod(a, b);
        if a == 0 {
            return (b, 0);
        }

        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; // |m1 * u| <= |m1| * s <= b

            swap(&mut s, &mut t);
            swap(&mut m0, &mut m1);
        }
        if m0 < 0 {
            m0 += b / s;
        }
        (s, m0)
    }

    /* const */
    pub(crate) fn primitive_root(m: i32) -> i32 {
        match m {
            2 => return 1,
            167_772_161 => return 3,
            469_762_049 => return 3,
            754_974_721 => return 11,
            998_244_353 => return 3,
            _ => {}
        }

        let mut divs = [0; 20];
        divs[0] = 2;
        let mut cnt = 1;
        let mut x = (m - 1) / 2;
        while x % 2 == 0 {
            x /= 2;
        }
        for i in (3..std::i32::MAX).step_by(2) {
            if i as i64 * i as i64 > x as i64 {
                break;
            }
            if x % i == 0 {
                divs[cnt] = i;
                cnt += 1;
                while x % i == 0 {
                    x /= i;
                }
            }
        }
        if x > 1 {
            divs[cnt] = x;
            cnt += 1;
        }
        let mut g = 2;
        loop {
            if (0..cnt).all(|i| pow_mod(g, ((m - 1) / divs[i]) as i64, m) != 1) {
                break g as i32;
            }
            g += 1;
        }
    }
}
pub mod modint {

    use crate::internal_math;
    use std::{
        cell::RefCell,
        convert::{Infallible, TryInto as _},
        fmt,
        hash::{Hash, Hasher},
        iter::{Product, Sum},
        marker::PhantomData,
        ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
        str::FromStr,
        sync::atomic::{self, AtomicU32, AtomicU64},
        thread::LocalKey,
    };

    pub type ModInt1000000007 = StaticModInt<Mod1000000007>;
    pub type ModInt998244353 = StaticModInt<Mod998244353>;
    pub type ModInt = DynamicModInt<DefaultId>;

    #[derive(Copy, Clone, Eq, PartialEq)]
    #[repr(transparent)]
    pub struct StaticModInt<M> {
        val: u32,
        phantom: PhantomData<fn() -> M>,
    }

    impl<M: Modulus> StaticModInt<M> {
        #[inline(always)]
        pub fn modulus() -> u32 {
            M::VALUE
        }

        #[inline]
        pub fn new<T: RemEuclidU32>(val: T) -> Self {
            Self::raw(val.rem_euclid_u32(M::VALUE))
        }

        #[inline]
        pub fn raw(val: u32) -> Self {
            Self {
                val,
                phantom: PhantomData,
            }
        }

        #[inline]
        pub fn val(self) -> u32 {
            self.val
        }

        #[inline]
        pub fn pow(self, n: u64) -> Self {
            <Self as ModIntBase>::pow(self, n)
        }

        #[inline]
        pub fn inv(self) -> Self {
            if M::HINT_VALUE_IS_PRIME {
                if self.val() == 0 {
                    panic!("attempt to divide by zero");
                }
                debug_assert!(
                    internal_math::is_prime(M::VALUE.try_into().unwrap()),
                    "{} is not a prime number",
                    M::VALUE,
                );
                self.pow((M::VALUE - 2).into())
            } else {
                Self::inv_for_non_prime_modulus(self)
            }
        }
    }

    impl<M: Modulus> ModIntBase for StaticModInt<M> {
        #[inline(always)]
        fn modulus() -> u32 {
            Self::modulus()
        }

        #[inline]
        fn raw(val: u32) -> Self {
            Self::raw(val)
        }

        #[inline]
        fn val(self) -> u32 {
            self.val()
        }

        #[inline]
        fn inv(self) -> Self {
            self.inv()
        }
    }

    pub trait Modulus: 'static + Copy + Eq {
        const VALUE: u32;
        const HINT_VALUE_IS_PRIME: bool;

        fn butterfly_cache() -> &'static LocalKey<RefCell<Option<ButterflyCache<Self>>>>;
    }

    #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
    pub enum Mod1000000007 {}

    impl Modulus for Mod1000000007 {
        const VALUE: u32 = 1_000_000_007;
        const HINT_VALUE_IS_PRIME: bool = true;

        fn butterfly_cache() -> &'static LocalKey<RefCell<Option<ButterflyCache<Self>>>> {
            thread_local! {
                static BUTTERFLY_CACHE: RefCell<Option<ButterflyCache<Mod1000000007>>> = RefCell::default();
            }
            &BUTTERFLY_CACHE
        }
    }

    #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
    pub enum Mod998244353 {}

    impl Modulus for Mod998244353 {
        const VALUE: u32 = 998_244_353;
        const HINT_VALUE_IS_PRIME: bool = true;

        fn butterfly_cache() -> &'static LocalKey<RefCell<Option<ButterflyCache<Self>>>> {
            thread_local! {
                static BUTTERFLY_CACHE: RefCell<Option<ButterflyCache<Mod998244353>>> = RefCell::default();
            }
            &BUTTERFLY_CACHE
        }
    }

    pub struct ButterflyCache<M> {
        pub(crate) sum_e: Vec<StaticModInt<M>>,
        pub(crate) sum_ie: Vec<StaticModInt<M>>,
    }

    #[derive(Copy, Clone, Eq, PartialEq)]
    #[repr(transparent)]
    pub struct DynamicModInt<I> {
        val: u32,
        phantom: PhantomData<fn() -> I>,
    }

    impl<I: Id> DynamicModInt<I> {
        #[inline]
        pub fn modulus() -> u32 {
            I::companion_barrett().umod()
        }

        #[inline]
        pub fn set_modulus(modulus: u32) {
            if modulus == 0 {
                panic!("the modulus must not be 0");
            }
            I::companion_barrett().update(modulus);
        }

        #[inline]
        pub fn new<T: RemEuclidU32>(val: T) -> Self {
            <Self as ModIntBase>::new(val)
        }

        #[inline]
        pub fn raw(val: u32) -> Self {
            Self {
                val,
                phantom: PhantomData,
            }
        }

        #[inline]
        pub fn val(self) -> u32 {
            self.val
        }

        #[inline]
        pub fn pow(self, n: u64) -> Self {
            <Self as ModIntBase>::pow(self, n)
        }

        #[inline]
        pub fn inv(self) -> Self {
            Self::inv_for_non_prime_modulus(self)
        }
    }

    impl<I: Id> ModIntBase for DynamicModInt<I> {
        #[inline]
        fn modulus() -> u32 {
            Self::modulus()
        }

        #[inline]
        fn raw(val: u32) -> Self {
            Self::raw(val)
        }

        #[inline]
        fn val(self) -> u32 {
            self.val()
        }

        #[inline]
        fn inv(self) -> Self {
            self.inv()
        }
    }

    pub trait Id: 'static + Copy + Eq {
        fn companion_barrett() -> &'static Barrett;
    }

    #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
    pub enum DefaultId {}

    impl Id for DefaultId {
        fn companion_barrett() -> &'static Barrett {
            static BARRETT: Barrett = Barrett::default();
            &BARRETT
        }
    }

    pub struct Barrett {
        m: AtomicU32,
        im: AtomicU64,
    }

    impl Barrett {
        #[inline]
        pub const fn new(m: u32) -> Self {
            Self {
                m: AtomicU32::new(m),
                im: AtomicU64::new((-1i64 as u64 / m as u64).wrapping_add(1)),
            }
        }

        #[inline]
        const fn default() -> Self {
            Self::new(998_244_353)
        }

        #[inline]
        fn update(&self, m: u32) {
            let im = (-1i64 as u64 / m as u64).wrapping_add(1);
            self.m.store(m, atomic::Ordering::SeqCst);
            self.im.store(im, atomic::Ordering::SeqCst);
        }

        #[inline]
        fn umod(&self) -> u32 {
            self.m.load(atomic::Ordering::SeqCst)
        }

        #[inline]
        fn mul(&self, a: u32, b: u32) -> u32 {
            let m = self.m.load(atomic::Ordering::SeqCst);
            let im = self.im.load(atomic::Ordering::SeqCst);
            internal_math::mul_mod(a, b, m, im)
        }
    }

    impl Default for Barrett {
        #[inline]
        fn default() -> Self {
            Self::default()
        }
    }

    pub trait ModIntBase:
        Default
        + FromStr
        + From<i8>
        + From<i16>
        + From<i32>
        + From<i64>
        + From<i128>
        + From<isize>
        + From<u8>
        + From<u16>
        + From<u32>
        + From<u64>
        + From<u128>
        + From<usize>
        + Copy
        + Eq
        + Hash
        + fmt::Display
        + fmt::Debug
        + Neg<Output = Self>
        + Add<Output = Self>
        + Sub<Output = Self>
        + Mul<Output = Self>
        + Div<Output = Self>
        + AddAssign
        + SubAssign
        + MulAssign
        + DivAssign
    {
        fn modulus() -> u32;

        fn raw(val: u32) -> Self;

        fn val(self) -> u32;

        fn inv(self) -> Self;

        #[inline]
        fn new<T: RemEuclidU32>(val: T) -> Self {
            Self::raw(val.rem_euclid_u32(Self::modulus()))
        }

        #[inline]
        fn pow(self, mut n: u64) -> Self {
            let mut x = self;
            let mut r = Self::raw(1);
            while n > 0 {
                if n & 1 == 1 {
                    r *= x;
                }
                x *= x;
                n >>= 1;
            }
            r
        }
    }

    pub trait RemEuclidU32 {
        fn rem_euclid_u32(self, modulus: u32) -> u32;
    }

    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);

    trait InternalImplementations: ModIntBase {
        #[inline]
        fn inv_for_non_prime_modulus(this: Self) -> Self {
            let (gcd, x) = internal_math::inv_gcd(this.val().into(), Self::modulus().into());
            if gcd != 1 {
                panic!("the multiplicative inverse does not exist");
            }
            Self::new(x)
        }

        #[inline]
        fn default_impl() -> Self {
            Self::raw(0)
        }

        #[inline]
        fn from_str_impl(s: &str) -> Result<Self, Infallible> {
            Ok(s.parse::<i64>()
                .map(Self::new)
                .unwrap_or_else(|_| todo!("parsing as an arbitrary precision integer?")))
        }

        #[inline]
        fn hash_impl(this: &Self, state: &mut impl Hasher) {
            this.val().hash(state)
        }

        #[inline]
        fn display_impl(this: &Self, f: &mut fmt::Formatter) -> fmt::Result {
            fmt::Display::fmt(&this.val(), f)
        }

        #[inline]
        fn debug_impl(this: &Self, f: &mut fmt::Formatter) -> fmt::Result {
            fmt::Debug::fmt(&this.val(), f)
        }

        #[inline]
        fn neg_impl(this: Self) -> Self {
            Self::sub_impl(Self::raw(0), this)
        }

        #[inline]
        fn add_impl(lhs: Self, rhs: Self) -> Self {
            let modulus = Self::modulus();
            let mut val = lhs.val() + rhs.val();
            if val >= modulus {
                val -= modulus;
            }
            Self::raw(val)
        }

        #[inline]
        fn sub_impl(lhs: Self, rhs: Self) -> Self {
            let modulus = Self::modulus();
            let mut val = lhs.val().wrapping_sub(rhs.val());
            if val >= modulus {
                val = val.wrapping_add(modulus)
            }
            Self::raw(val)
        }

        fn mul_impl(lhs: Self, rhs: Self) -> Self;

        #[inline]
        fn div_impl(lhs: Self, rhs: Self) -> Self {
            Self::mul_impl(lhs, rhs.inv())
        }
    }

    impl<M: Modulus> InternalImplementations for StaticModInt<M> {
        #[inline]
        fn mul_impl(lhs: Self, rhs: Self) -> Self {
            Self::raw((u64::from(lhs.val()) * u64::from(rhs.val()) % u64::from(M::VALUE)) as u32)
        }
    }

    impl<I: Id> InternalImplementations for DynamicModInt<I> {
        #[inline]
        fn mul_impl(lhs: Self, rhs: Self) -> Self {
            Self::raw(I::companion_barrett().mul(lhs.val, rhs.val))
        }
    }

    macro_rules! impl_basic_traits {
    () => {};
    (impl <$generic_param:ident : $generic_param_bound:tt> _ for $self:ty; $($rest:tt)*) => {
        impl <$generic_param: $generic_param_bound> Default for $self {
            #[inline]
            fn default() -> Self {
                Self::default_impl()
            }
        }

        impl <$generic_param: $generic_param_bound> FromStr for $self {
            type Err = Infallible;

            #[inline]
            fn from_str(s: &str) -> Result<Self, Infallible> {
                Self::from_str_impl(s)
            }
        }

        impl<$generic_param: $generic_param_bound, V: RemEuclidU32> From<V> for $self {
            #[inline]
            fn from(from: V) -> Self {
                Self::new(from)
            }
        }

        #[allow(clippy::derive_hash_xor_eq)]
        impl<$generic_param: $generic_param_bound> Hash for $self {
            #[inline]
            fn hash<H: Hasher>(&self, state: &mut H) {
                Self::hash_impl(self, state)
            }
        }

        impl<$generic_param: $generic_param_bound> fmt::Display for $self {
            #[inline]
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                Self::display_impl(self, f)
            }
        }

        impl<$generic_param: $generic_param_bound> fmt::Debug for $self {
            #[inline]
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                Self::debug_impl(self, f)
            }
        }

        impl<$generic_param: $generic_param_bound> Neg for $self {
            type Output = $self;

            #[inline]
            fn neg(self) -> $self {
                Self::neg_impl(self)
            }
        }

        impl<$generic_param: $generic_param_bound> Neg for &'_ $self {
            type Output = $self;

            #[inline]
            fn neg(self) -> $self {
                <$self>::neg_impl(*self)
            }
        }

        impl_basic_traits!($($rest)*);
    };
}

    impl_basic_traits! {
        impl <M: Modulus> _ for StaticModInt<M> ;
        impl <I: Id     > _ for DynamicModInt<I>;
    }

    macro_rules! impl_bin_ops {
    () => {};
    (for<$($generic_param:ident : $generic_param_bound:tt),*> <$lhs_ty:ty> ~ <$rhs_ty:ty> -> $output:ty { { $lhs_body:expr } ~ { $rhs_body:expr } } $($rest:tt)*) => {
        impl <$($generic_param: $generic_param_bound),*> Add<$rhs_ty> for $lhs_ty {
            type Output = $output;

            #[inline]
            fn add(self, rhs: $rhs_ty) -> $output {
                <$output>::add_impl(apply($lhs_body, self), apply($rhs_body, rhs))
            }
        }

        impl <$($generic_param: $generic_param_bound),*> Sub<$rhs_ty> for $lhs_ty {
            type Output = $output;

            #[inline]
            fn sub(self, rhs: $rhs_ty) -> $output {
                <$output>::sub_impl(apply($lhs_body, self), apply($rhs_body, rhs))
            }
        }

        impl <$($generic_param: $generic_param_bound),*> Mul<$rhs_ty> for $lhs_ty {
            type Output = $output;

            #[inline]
            fn mul(self, rhs: $rhs_ty) -> $output {
                <$output>::mul_impl(apply($lhs_body, self), apply($rhs_body, rhs))
            }
        }

        impl <$($generic_param: $generic_param_bound),*> Div<$rhs_ty> for $lhs_ty {
            type Output = $output;

            #[inline]
            fn div(self, rhs: $rhs_ty) -> $output {
                <$output>::div_impl(apply($lhs_body, self), apply($rhs_body, rhs))
            }
        }

        impl_bin_ops!($($rest)*);
    };
}

    macro_rules! impl_assign_ops {
    () => {};
    (for<$($generic_param:ident : $generic_param_bound:tt),*> <$lhs_ty:ty> ~= <$rhs_ty:ty> { _ ~= { $rhs_body:expr } } $($rest:tt)*) => {
        impl <$($generic_param: $generic_param_bound),*> AddAssign<$rhs_ty> for $lhs_ty {
            #[inline]
            fn add_assign(&mut self, rhs: $rhs_ty) {
                *self = *self + apply($rhs_body, rhs);
            }
        }

        impl <$($generic_param: $generic_param_bound),*> SubAssign<$rhs_ty> for $lhs_ty {
            #[inline]
            fn sub_assign(&mut self, rhs: $rhs_ty) {
                *self = *self - apply($rhs_body, rhs);
            }
        }

        impl <$($generic_param: $generic_param_bound),*> MulAssign<$rhs_ty> for $lhs_ty {
            #[inline]
            fn mul_assign(&mut self, rhs: $rhs_ty) {
                *self = *self * apply($rhs_body, rhs);
            }
        }

        impl <$($generic_param: $generic_param_bound),*> DivAssign<$rhs_ty> for $lhs_ty {
            #[inline]
            fn div_assign(&mut self, rhs: $rhs_ty) {
                *self = *self / apply($rhs_body, rhs);
            }
        }

        impl_assign_ops!($($rest)*);
    };
}

    #[inline]
    fn apply<F: FnOnce(X) -> O, X, O>(f: F, x: X) -> O {
        f(x)
    }

    impl_bin_ops! {
        for<M: Modulus> <StaticModInt<M>     > ~ <StaticModInt<M>     > -> StaticModInt<M>  { { |x| x  } ~ { |x| x  } }
        for<M: Modulus> <StaticModInt<M>     > ~ <&'_ StaticModInt<M> > -> StaticModInt<M>  { { |x| x  } ~ { |&x| x } }
        for<M: Modulus> <&'_ StaticModInt<M> > ~ <StaticModInt<M>     > -> StaticModInt<M>  { { |&x| x } ~ { |x| x  } }
        for<M: Modulus> <&'_ StaticModInt<M> > ~ <&'_ StaticModInt<M> > -> StaticModInt<M>  { { |&x| x } ~ { |&x| x } }
        for<I: Id     > <DynamicModInt<I>    > ~ <DynamicModInt<I>    > -> DynamicModInt<I> { { |x| x  } ~ { |x| x  } }
        for<I: Id     > <DynamicModInt<I>    > ~ <&'_ DynamicModInt<I>> -> DynamicModInt<I> { { |x| x  } ~ { |&x| x } }
        for<I: Id     > <&'_ DynamicModInt<I>> ~ <DynamicModInt<I>    > -> DynamicModInt<I> { { |&x| x } ~ { |x| x  } }
        for<I: Id     > <&'_ DynamicModInt<I>> ~ <&'_ DynamicModInt<I>> -> DynamicModInt<I> { { |&x| x } ~ { |&x| x } }

        for<M: Modulus, T: RemEuclidU32> <StaticModInt<M>     > ~ <T> -> StaticModInt<M>  { { |x| x  } ~ { StaticModInt::<M>::new } }
        for<I: Id     , T: RemEuclidU32> <DynamicModInt<I>    > ~ <T> -> DynamicModInt<I> { { |x| x  } ~ { DynamicModInt::<I>::new } }
    }

    impl_assign_ops! {
        for<M: Modulus> <StaticModInt<M> > ~= <StaticModInt<M>     > { _ ~= { |x| x  } }
        for<M: Modulus> <StaticModInt<M> > ~= <&'_ StaticModInt<M> > { _ ~= { |&x| x } }
        for<I: Id     > <DynamicModInt<I>> ~= <DynamicModInt<I>    > { _ ~= { |x| x  } }
        for<I: Id     > <DynamicModInt<I>> ~= <&'_ DynamicModInt<I>> { _ ~= { |&x| x } }

        for<M: Modulus, T: RemEuclidU32> <StaticModInt<M> > ~= <T> { _ ~= { StaticModInt::<M>::new } }
        for<I: Id,      T: RemEuclidU32> <DynamicModInt<I>> ~= <T> { _ ~= { DynamicModInt::<I>::new } }
    }

    macro_rules! impl_folding {
    () => {};
    (impl<$generic_param:ident : $generic_param_bound:tt> $trait:ident<_> for $self:ty { fn $method:ident(_) -> _ { _($unit:expr, $op:expr) } } $($rest:tt)*) => {
        impl<$generic_param: $generic_param_bound> $trait<Self> for $self {
            #[inline]
            fn $method<S>(iter: S) -> Self
            where
                S: Iterator<Item = Self>,
            {
                iter.fold($unit, $op)
            }
        }

        impl<'a, $generic_param: $generic_param_bound> $trait<&'a Self> for $self {
            #[inline]
            fn $method<S>(iter: S) -> Self
            where
                S: Iterator<Item = &'a Self>,
            {
                iter.fold($unit, $op)
            }
        }

        impl_folding!($($rest)*);
    };
}

    impl_folding! {
        impl<M: Modulus> Sum<_>     for StaticModInt<M>  { fn sum(_)     -> _ { _(Self::raw(0), Add::add) } }
        impl<M: Modulus> Product<_> for StaticModInt<M>  { fn product(_) -> _ { _(Self::raw(1), Mul::mul) } }
        impl<I: Id     > Sum<_>     for DynamicModInt<I> { fn sum(_)     -> _ { _(Self::raw(0), Add::add) } }
        impl<I: Id     > Product<_> for DynamicModInt<I> { fn product(_) -> _ { _(Self::raw(1), Mul::mul) } }
    }
}


use std::io::{stdin};
use std::str::FromStr;
use std::iter::from_fn;
use std::sync::Once;

#[derive(Default)]
struct Scanner {
    buffer: Vec<String>
}
impl Scanner {
    #[allow(dead_code)]
    fn next<T:FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }

    #[allow(dead_code)]
    fn next_vec<T:FromStr> (&mut self, n:isize) -> Vec<T> {
        let mut count = 0;
        let  res = from_fn(| | {
            if count < n {
                count += 1;
                Some(self.next::<T>())
            } else {
                None
            }
        });
        res.collect()
    }
}

fn main() {
    let mut scan = Scanner::default();
    solve(&mut scan)
}

const MOD:u64 = 1000000007;

static INIT: Once = Once::new();
static mut FACTS:Vec<u64> = vec![];

fn fact(n:u64) -> u64 {
	unsafe {
		INIT.call_once(|| {
			FACTS.push(1);
			for i in 1..=1000 {
				FACTS.push((FACTS[i-1]*i as u64)%MOD);
			}
		});
		FACTS[n as usize]
	}
}

fn mod_pow(mut base: u64, mut exp: u64, modulus: u64) -> u64 {
    if modulus == 1 { return 0 }
    let mut result = 1;
    base = base % modulus;
    while exp > 0 {
        if exp % 2 == 1 {
            result = result * base % modulus;
        }
        exp = exp >> 1;
        base = base * base % modulus
    }
    result
}

fn inverse(base: u64) -> u64 {
	mod_pow(base, MOD-2, MOD)
}

fn perms(n:u64, x:u64) -> u64 {
	(fact(n) * inverse(fact(n-x)))%MOD
}

fn solve(scan:&mut Scanner) {
	let n:u64 = scan.next();
	let x:u64 = scan.next();
	let p:u64 = scan.next();
	let mut ltx = Vec::new();
	let mut gtx = Vec::new();
	let mut l = 0;
	let mut r = n;
	let mut m;
	while l < r {
		m = (l + r)/2;
		if m < p {
			ltx.push(m);
			l = m+1;
		} else if m > p {
			gtx.push(m);
			r = m
		} else {
			l = m+1;
		}
	}
	if x <= ltx.len() as u64 || n - x < gtx.len() as u64 {
		println!("0");
		return;
	}
	let free = n - ltx.len() as u64 - gtx.len() as u64 - 1;
	println!("{}",
		((perms(free, free) *
		perms(x-1, ltx.len() as u64))%MOD *
		perms(n-x, gtx.len() as u64))%MOD);
}


#[allow(unused_imports)]
use std::io;
use std::cmp::{min, max};
use std::mem;
use std::str::FromStr;
pub struct Scanner<B> {
    reader: B,
    buffer: Vec<String>,
}

impl<B: io::BufRead> Scanner<B> {
    pub fn new(reader: B) -> Scanner<B> {
        Scanner {
            reader: reader,
            buffer: Vec::new(),
        }
    }

    /// Use "turbofish" syntax next::<T>() to select data type of next token.
    pub fn next<T: ::std::str::FromStr>(&mut self) -> T
        where
            T::Err: ::std::fmt::Debug,
    {
        if let Some(front) = self.buffer.pop() {
            front.parse::<T>().expect(&front)
        } else {
            let mut input = String::new();
            self.reader.read_line(&mut input).expect("Line not read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
            self.next()
        }
    }

    pub fn next_vec<T: ::std::str::FromStr>(&mut self, len: usize) -> Vec<T>
        where
            T::Err: ::std::fmt::Debug,
    {
        (0..len).map(|_| self.next::<T>()).collect::<Vec<T>>()
    }
}

fn main1() {
    let stdin = io::stdin();
    let mut input = Scanner::new(stdin.lock());
    let n = input.next::<usize>();
    let m = input.next::<usize>();
    let pixels: Vec<String> = input.next_vec(n * m);
    println!("{}", if pixels.iter().all(|x| x == "W" || x == "B" || x == 'G') {"#Black&White"} else {"#Color"});

}

fn main() {
    std::thread::Builder::new().stack_size(50 << 20)
        .spawn(main1).unwrap().join().unwrap();
}


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();
    );

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


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 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 maxima = [
        (a+b)*c,
        a*b+c,
        a+b*c,
        a+b+c,
        a*b*c,
        a*(b+c)
    ]
    .iter()
    .max()
    .unwrap();

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


use std::io::{self, BufRead};

fn it() -> impl Iterator<Item=char> {
    (0..).flat_map(|i| i.to_string().chars().collect::<Vec<_>>())
}

fn main() {
    let line = io::stdin().lock().lines().next().expect("input").expect("UTF-8");
    let index: usize = line.parse().expect("Numeric value");

    println!("{}", it().skip(index).next().unwrap());
}

#[test]
fn vectors() {
    let in_out = [(7, '7'), (21, '5')];

    for (i, o) in &in_out {
        assert_eq!(it().skip(*i).next().unwrap(), *o);
    }
}


#![allow(non_snake_case, unused_imports, deprecated, dead_code)]

// Input macros
macro_rules! input { (source = $s:expr, $($r:tt)*) => { let mut iter = $s.split_whitespace(); let mut next = || { iter.next().unwrap() }; input_inner!{next, $($r)*} }; ($($r:tt)*) => { let stdin = std::io::stdin(); let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock())); let mut next = move || -> String{ bytes.by_ref().map(|r|r.unwrap() as char).skip_while(|c|c.is_whitespace()).take_while(|c|!c.is_whitespace()).collect() }; input_inner!{next, $($r)*} }; }
macro_rules! input_inner { ($next:expr) => {}; ($next:expr, ) => {}; ($next:expr, $var:ident : $t:tt $($r:tt)*) => { let $var = read_value!($next, $t); input_inner!{$next $($r)*} }; ($next:expr, mut $var:ident : $t:tt $($r:tt)*) => { let mut $var = read_value!($next, $t); input_inner!{$next $($r)*} }; }
macro_rules! read_value { ($next:expr, ( $($t:tt),* )) => { ( $(read_value!($next, $t)),* ) }; ($next:expr, [ $t:tt ; $len:expr ]) => { (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>() }; ($next:expr, [ $t:tt ]) => { { let len = read_value!($next, usize); (0..len).map(|_| read_value!($next, $t)).collect::<Vec<_>>() } }; ($next:expr, chars) => { read_value!($next, String).chars().collect::<Vec<char>>() }; ($next:expr, bytes) => { read_value!($next, String).into_bytes() }; ($next:expr, usize1) => { read_value!($next, usize) - 1 }; ($next:expr, $t:ty) => { $next().parse::<$t>().expect("Parse error") }; }

// Module
use std::cmp::{min,max};
use std::collections::{VecDeque,HashMap,HashSet,BTreeMap,BTreeSet,BinaryHeap};
// Module for v1.15.1
use std::ascii::AsciiExt; // deprecated since 1.26.0: use inherent method instead

// Functions

// Main
fn main() {

    input! {
        S: String,
    }

    let hello = vec!['h','e','l','l','o'];

    let mut i = 0;
    for c in S.chars() {
        if c==hello[i] {
            i += 1;
        }
        if i==5 {
            break;
        }
    }

    println!("{}", if i==5{"YES"else{"NO"}});
}


use std::io;

fn convert(s: &str) -> i64 {
    return s.parse().unwrap();
}

fn main(){
    let mut input = String::new();
    io::stdin().read_line(&mut input).unwrap();
    let mut iter = read.split_whitespace().map(convert);
    let mut l = iter.next().unwrap_or(-1);
    let r = iter.next().unwrap_or(-1);
    if l != r{
        l = 2;
    }
    println!("{}", l);
}


use std::cmp::min;

#[allow(unused_macros)]
macro_rules! read {
    ($out:ident as $type:ty) => {
        let mut inner = String::new();
        std::io::stdin().read_line(&mut inner).expect("A String");
        let $out = inner.trim().parse::<$type>().expect("Parsable");
    };
}

#[allow(unused_macros)]
macro_rules! read_str {
    ($out:ident) => {
        let mut inner = String::new();
        std::io::stdin().read_line(&mut inner).expect("A String");
        let $out = inner.trim();
    };
}

#[allow(unused_macros)]
macro_rules! read_vec {
    ($out:ident as $type:ty) => {
        let mut inner = String::new();
        std::io::stdin().read_line(&mut inner).unwrap();
        let $out = inner
            .trim()
            .split_whitespace()
            .map(|s| s.parse::<$type>().unwrap())
            .collect::<Vec<$type>>();
    };
}

fn solve(mut v: u32) -> u32 {
    let mut d: u32 = 9;
    let mut m: u32 = 1;
    let mut result = 0;
    while v > 0 {
        let min_d = min(v, d);
        v -= min_d;
        result += m * min_d;
        d -= 1;
        m *= 10;
    }
    result
}


#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define int long long
#define rep(x, y, z) for (int x = y; x <= (z); x++)
#define rep1(x, y, z) for (int x = y; x < (z); x++)
#define dep(x, y, z) for (int x = y; x >= (z); x--)
#define dep1(x, y, z) for (int x = y; x > (z); x--)
#define sz(x) ((int)x.size())
#define all(x) x.begin(), x.end()
#define mem(a, b) memset(a, b, sizeof a)
#define endl '\n'

typedef vector<int> vi;
typedef unsigned long long ull;
typedef pair<int, int> pii;

template<class T> void minn(T& a, T b) {if (a > b) a = b;}
template<class T> void maxx(T& a, T b) {if (a < b) a = b;}

const int mod = 998244353;
const int N = 2e5 + 5;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
int n;
int norm(int x) {
    if (x < 0) {
        x += mod;
    }
    if (x >= mod) {
        x -= mod;
    }
    return x;
}
template<class T>
T mfast(T a, int b) {
    T res = 1;
    for (; b; b /= 2, a *= a) {
        if (b % 2) {
            res *= a;
        }
    }
    return res;
}
struct Z {
    int x;
    Z(int x = 0) : x(norm(x)) {}
    int val() const {
        return x;
    }
    Z operator-() const {
        return Z(norm(mod - x));
    }
    Z inv() const {
        assert(x != 0);
        return mfast(*this, mod - 2);
    }
    Z &operator*=(const Z &rhs) {
        x = ll(x) * rhs.x % mod;
        return *this;
    }
    Z &operator+=(const Z &rhs) {
        x = norm(x + rhs.x);
        return *this;
    }
    Z &operator-=(const Z &rhs) {
        x = norm(x - rhs.x);
        return *this;
    }
    Z &operator/=(const Z &rhs) {
        return *this *= rhs.inv();
    }
    Z &operator++() {
        this->x = norm(this->x + 1);
        return *this;
    }
    Z &operator--() {
        this->x = norm(this->x - 1);
        return *this;
    }
    friend Z operator*(const Z &lhs, const Z &rhs) {
        Z res = lhs;
        res *= rhs;
        return res;
    }
    friend Z operator+(const Z &lhs, const Z &rhs) {
        Z res = lhs;
        res += rhs;
        return res;
    }
    friend Z operator-(const Z &lhs, const Z &rhs) {
        Z res = lhs;
        res -= rhs;
        return res;
    }
    friend Z operator/(const Z &lhs, const Z &rhs) {
        Z res = lhs;
        res /= rhs;
        return res;
    }
    friend ostream& operator<<(ostream& os, const Z& lhs) {
        os << lhs.x;
        return os;
    }
    friend istream& operator>>(istream& is, Z& lhs) {
        ll x;
        cin >> x;
        lhs.x = norm(x);
        return is;
    }
};

bool prime(int n) {
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            while (n % i == 0) n /= i;
            return false;
        }
    }
    return true;
}
void solve() {
    ll m;
    cin >> n;
    cin >> m;
    Z tmp = m % mod;
    Z ans = 0;
    rep (i, 2, n) {
        tmp = tmp * (m % mod);
        ans += tmp;
    }
    ll lc = 1;
    vector<Z> x(n + 1);
    rep (i, 2, n) {
        if (prime(i)) {
            lc = lcm(i, lc);
        }
        if (lc > m) {
            break;
        }
        x[i] = (m / lc) % mod;
    }
    x[1] = m % mod;
    rep (i, 2, n) {
        x[i] = x[i] * x[i - 1];
        ans -= x[i];
    }
    cout << ans  << endl;
}
signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int T = 1;
    for (int i = 1; i <= T; i++) {
        solve();
    }
}


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

    std::io::stdin().read_line(&mut input).unwrap();

    let mut it = input.split_whitespace().map(|x| x.parse::<usize>().unwrap());

    let (n, k) = (it.next().unwrap(), it.next().unwrap());

    let mut input = String::new();

    std::io::stdin().read_line(&mut input).unwrap();

    let input = input.trim();

    let mut last_poss = [0; 26];

    for (i, c) in input.chars().map(|c| c.to_digit(36).unwrap() - 10).enumerate() {
        last_poss[c as usize] = i;
    }

    let mut statuses = [0; 26];
    for (i, c) in input.chars().map(|c| c.to_digit(36).unwrap() - 10).enumerate() {
        if i >= last_poss[c as usize] {
            statuses[c as usize] = 0;
        } else {
            statuses[c as usize] = 1;
        }
        let cur_gc:usize = statuses.iter().sum();
        if cur_gc > k {
            println!("YES");
            std::process::exit(0);
        }
    }

    println!("NO");
}


use std::io::{self, BufReader, Stdin};
use std::io::prelude::*;
use std::collections::BTreeSet;
use std::iter::Map;
use std::str::SplitWhitespace;

fn main() {
    let mut reader = ReadIn::new();

    reader.read_line();
    let a: BTreeSet<i32> = reader.read_iter().collect();
    let b: BTreeSet<i32> = reader.read_iter().collect();
    let c: BTreeSet<i32> = a.intersection(&b).map(|&x| x).collect();
    let res = (if !c.is_empty() { c.iter().map(|&x| x).next() } else {
        a.iter().next().and_then(
            |ax| b.iter().next().map(
                |bx| ax.min(bx) * 10 + ax.max(bx)))
    }).unwrap();
    print!("{}", res);
}

struct ReadIn { reader: BufReader<Stdin>, buf: String }

impl ReadIn {
    fn new() -> ReadIn { ReadIn { reader: BufReader::new(io::stdin()), buf: String::new() } }
    fn read_i32(s: &str) -> i32 { s.parse().unwrap() }
    fn read_line(&mut self) {
        self.buf.clear();
        self.reader.read_line(&mut self.buf);
    }
    fn read_iter(&mut self) -> Map<SplitWhitespace, fn(&str) -> i32> {
        self.read_line();
        self.buf.split_whitespace().map(ReadIn::read_i32)
    }
    fn read_vec(&mut self) -> Vec<i32> {
        self.read_iter().collect()
    }
}


use std::io::{self, BufReader, Stdin};
use std::io::prelude::*;
use std::collections::BTreeSet;
use std::iter::Map;
use std::str::SplitWhitespace;

fn main() {
    let mut reader = ReadIn::new();

    reader.read_line();
    let a: BTreeSet<i32> = reader.read_iter().collect();
    let b: BTreeSet<i32> = reader.read_iter().collect();
    let c: BTreeSet<i32> = a.intersection(&b).map(|&x| x).collect();
    let res = (if !c.is_empty() { c.iter().map(|&x| x).next() } else {
        a.iter().next().and_then(
            |&ax| b.iter().next().map(
                |&bx| ax.min(bx) * 10 + ax.max(bx)))
    }).unwrap();
    print!("{}", res);
}

struct ReadIn { reader: BufReader<Stdin>, buf: String }

impl ReadIn {
    fn new() -> ReadIn { ReadIn { reader: BufReader::new(io::stdin()), buf: String::new() } }
    fn read_i32(s: &str) -> i32 { s.parse().unwrap() }
    fn read_line(&mut self) {
        self.buf.clear();
        self.reader.read_line(&mut self.buf);
    }
    fn read_iter(&mut self) -> Map<SplitWhitespace, fn(&str) -> i32> {
        self.read_line();
        self.buf.split_whitespace().map(ReadIn::read_i32)
    }
    fn read_vec(&mut self) -> Vec<i32> {
        self.read_iter().collect()
    }
}


use rand::prelude::*;
use std::boxed::Box;
use std::cmp::*;
use std::io;
#[derive(Clone)]
struct Node<T: Ord + Clone> {
    pub key: T,
    pub weight: i64,
    pub left: Option<Box<Node<T>>>,
    pub right: Option<Box<Node<T>>>,
}

impl<T: Ord + Clone> Node<T> {
    fn new(value: T) -> Self {
        Node {
            key: value,
            weight: rand::random::<i64>(),
            left: None,
            right: None,
        }
    }

    pub fn split(
        node: Option<Box<Node<T>>>,
        key: &T,
    ) -> (Option<Box<Node<T>>>, Option<Box<Node<T>>>) {
        match node {
            None => (None, None),
            Some(mut node) => match node.key.cmp(key) {
                Ordering::Less => {
                    let (l, r) = Self::split(node.right, key);
                    node.right = l;
                    (Some(node), r)
                }
                _ => {
                    let (l, r) = Self::split(node.left, key);
                    node.left = r;
                    (l, Some(node))
                }
            },
        }
    }

    pub fn merge(left: Option<Box<Node<T>>>, right: Option<Box<Node<T>>>) -> Option<Box<Node<T>>> {
        match (left, right) {
            (None, None) => None,
            (left, None) => left,
            (None, right) => right,
            (Some(mut left), Some(mut right)) => match left.weight.cmp(&right.weight) {
                Ordering::Less => {
                    left.right = Self::merge(left.right, Some(right));
                    Some(left)
                }
                _ => {
                    right.left = Self::merge(Some(left), right.left);
                    Some(right)
                }
            },
        }
    }

    fn find(node: &Option<Box<Node<T>>>, key: &T) -> bool {
        match node {
            None => false,
            Some(node) => match node.key.cmp(key) {
                Ordering::Less => Self::find(&node.right, key),
                Ordering::Greater => Self::find(&node.left, key),
                Ordering::Equal => true,
            },
        }
    }

    fn less(node: &Box<Node<T>>) -> T {
        match node.left {
            None => node.key.clone(),
            Some(ref left) => Self::less(left),
        }
    }
}

struct Treap<T: Ord + Clone> {
    root: Option<Box<Node<T>>>,
}

impl<T: Ord + Clone + std::fmt::Display> Treap<T> {
    pub fn insert(&mut self, key: T) {
        let (mut l, r) = Node::split(self.root.take(), &key);
        l = Node::merge(l, Some(Box::new(Node::new(key))));
        self.root = Node::merge(l, r);
    }

    pub fn delete(&mut self, key: &T) {
        let (l, mut r) = Node::split(self.root.take(), key);
        r = match r {
            None => None,
            Some(node) => {
                if &node.key == key {
                    Node::merge(node.left, node.right)
                } else {
                    Some(node)
                }
            }
        };
        self.root = Node::merge(l, r);
    }

    pub fn find(&self, key: &T) -> bool {
        Node::find(&self.root, key)
    }

    pub fn less(&self) -> Option<T> {
        match self.root {
            Some(ref root) => Some(Node::less(root)),
            _ => None,
        }
    }

    pub fn new() -> Self {
        Treap { root: None }
    }
}

fn main() {
    let mut buffer = String::new();
    io::stdin().read_line(&mut buffer);
    buffer = String::new();
    io::stdin().read_line(&mut buffer);
    buffer.retain(|s| s != '\r' && s != '\n');
    let a: Vec<u64> = buffer
        .split_whitespace()
        .map(|n| n.parse::<u64>().unwrap())
        .collect();

    buffer = String::new();
    io::stdin().read_line(&mut buffer);
    buffer.retain(|s| s != '\r' && s != '\n');
    let b: Vec<u64> = buffer
        .split_whitespace()
        .map(|n| n.parse::<u64>().unwrap())
        .collect();

    let mut t1 = Treap::new();
    let mut t2 = Treap::new();
    //println!("{:?} | {:?}", &a, &b);
    for n in a {
        t1.insert(n);
    }
    for n in b {
        t2.insert(n);
    }
    let (m1, m2) = (t1.less().unwrap(), t2.less().unwrap());

    match m1.cmp(&m2) {
        Ordering::Less => println!("{}{}", m1, m2),
        Ordering::Greater => println!("{}{}", m2, m1),
        Ordering::Equal => println!("{}", m2),
    }
}


macro_rules! read_line {
    ($v:ident) => {
        let mut temp = String::new();
        std::io::stdin().read_line(&mut temp).unwrap();
        let $v = temp;
    };
    (var, $t:ty, $($v:ident), *) => {
        read_line!(input_line);
        let mut iter = parse_token!($t, input_line);
        $(
            let $v = iter.next().unwrap();
        )*
    };
    (vec, $t:ty, $v:ident) => {
        read_line!(input_line);
        let iter = parse_token!($t, input_line);
        let $v: Vec<$t> = iter.collect();
    };
    ($($v:ident; $t:ty), *) => {
        read_line!(input_line);
        let mut iter = input_line.split_whitespace();
        $(
            let $v: $t = iter.next().unwrap().parse().unwrap();
        )*
    };
}

macro_rules! parse_token {
    ($t:ty, $e:expr) => {
        $e.split_whitespace().map(|x| x.parse::<$t>().unwrap());
    };
}

fn main() {
    read_line!(k;u64, n;u64);
    let mut cnt = 0;
    for i in 1..(k + 1) {
        if k % i == 0 {
            cnt += 1;
        }
        if cnt == n {
            println!("{}", i);
            return;
        }
    }

    println!("-1");
}


fn main() -> std::io::Result<()> {
    let mut contents = String::new();
	std::io::stdin().read_line(&mut contents)?;
	let contents: Vec<&str> = contents.split("\r\n").collect();
	let contents: &str = contents[0];
	let _num:u32 = contents.parse().unwrap();
    let mut contents = String::new();
	std::io::stdin().read_line(&mut contents)?;
	let contents: Vec<&str> = contents.split("\r\n").collect();
	let contents: Vec<&str> = contents[0].split_whitespace().collect();
	let mut numbers: Vec<u32> = Vec::new();
	for number in contents {
		numbers.push(number.parse().unwrap());
	}
	let mut check: std::collections::HashMap<u32,u32> = std::collections::HashMap::new();
	for number in &numbers {
		let current = check.get_mut(number);
		//println!("{:?}", current);
		match current {
			None => check.insert(*number, 1),
			Some(numbera) => {
				let new = *numbera+1;
				check.insert(*number, new)
			}
		};
	}
	let mut max: u32 = 0;
	for number in &numbers {
		let cur = *check.get(number).unwrap();
		if cur > max{
			max = cur;
		}
	}
	println!("{}",max);
	Ok(())
}


fn main() -> std::io::Result<()> {
    let mut contents = String::new();
	std::io::stdin().read_line(&mut contents)?;
	let contents: Vec<&str> = contents.split("\r\n").collect();
	let contents: &str = contents[0];
	let _num:u32 = contents.parse().unwrap();
    let mut contents = String::new();
	std::io::stdin().read_line(&mut contents)?;
	let contents: Vec<&str> = contents.split("\r\n").collect();
	let contents: Vec<&str> = contents[0].split_whitespace().collect();
	let mut numbers: Vec<u32> = Vec::new();
	for number in contents {
		numbers.push(number.parse().unwrap());
	}
	let mut check: std::collections::HashMap<u32,u32> = std::collections::HashMap::new();
	for &number in &numbers {
		let current = &check.get(&number);
		//println!("{:?}", current);
		match current {
			None => check.insert(number, 1),
			Some(numbera) => {
				let new = *numbera+1;
				check.insert(number, new)
			}
		};
	}
	let mut max: u32 = 0;
	for number in &numbers {
		let cur = *check.get(number).unwrap();
		if cur > max{
			max = cur;
		}
	}
	println!("{}",max);
	Ok(())
}


fn main() -> std::io::Result<()> {
    let mut contents = String::new();
	std::io::stdin().read_line(&mut contents)?;
	let contents: Vec<&str> = contents.split("\r\n").collect();
	let contents: &str = contents[0];
	let _num:u32 = contents.parse().unwrap();
    let mut contents = String::new();
	std::io::stdin().read_line(&mut contents)?;
	let contents: Vec<&str> = contents.split("\r\n").collect();
	let contents: Vec<&str> = contents[0].split_whitespace().collect();
	let mut numbers: Vec<u32> = Vec::new();
	for number in contents {
		numbers.push(number.parse().unwrap());
	}
	let mut check: std::collections::HashMap<u32,u32> = std::collections::HashMap::new();
	for &number in &numbers {
		let current = &mut check.get(&number);
		//println!("{:?}", current);
		match current {
			None => check.insert(number, 1),
			Some(numbera) => {
				let new = *numbera+1;
				check.insert(number, new)
			}
		};
	}
	let mut max: u32 = 0;
	for number in &numbers {
		let cur = *check.get(number).unwrap();
		if cur > max{
			max = cur;
		}
	}
	println!("{}",max);
	Ok(())
}


fn main() -> std::io::Result<()> {
    let mut contents = String::new();
	std::io::stdin().read_line(&mut contents)?;
	let contents: Vec<&str> = contents.split("\r\n").collect();
	let contents: &str = contents[0];
	let _num:u32 = contents.parse().unwrap();
    let mut contents = String::new();
	std::io::stdin().read_line(&mut contents)?;
	let contents: Vec<&str> = contents.split("\r\n").collect();
	let contents: Vec<&str> = contents[0].split_whitespace().collect();
	let mut numbers: Vec<u32> = Vec::new();
	for number in contents {
		numbers.push(number.parse().unwrap());
	}
	let mut check: std::collections::HashMap<u32,u32> = std::collections::HashMap::new();
	for number in &numbers {
		let mut current = check.get(number);
		//println!("{:?}", current);
		match current {
			None => check.insert(*number, 1),
			Some(numbera) => check.insert(*number, *numbera+1)
		};
	}
	let mut max: u32 = 0;
	for number in &numbers {
		let cur = *check.get(number).unwrap();
		if cur > max{
			max = cur;
		}
	}
	println!("{}",max);
	Ok(())
}


use std::io;
use std::str;

pub struct Scanner<R> {
    reader: R,
    buffer: Vec<String>,
}

impl<R: io::BufRead> Scanner<R> {
    pub fn new(reader: R) -> Self {
        Self {
            reader,
            buffer: vec![],
        }
    }

    pub fn token<T: str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            self.reader.read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

fn digit_sum(x: i64) -> i64 {
    let mut x = x;
    let mut ans = 0;
    while x > 0 {
        ans += x % 10;
        x /= 10;
    }
    ans
}

fn solve<R: io::BufRead, W: io::Write>(scan: &mut Scanner<R>, out: &mut W) {
    let a: u32 = scan.token();
    let b: i64 = scan.token();
    let c: i64 = scan.token();
    let mut ans = Vec::new();

    for s_x in 1i64..=81i64 {
        let x = b * s_x.pow(a) + c;
        if x >= 1000000000 {
            break;
        }
        if x < digit_sum(x) == s_x {
            ans.push(x.to_string());
        }
    }
    writeln!(out, "{}", ans.len()).ok();
    writeln!(out, "{}", ans.join(" ")).ok();
}

fn main() {
    let (stdin, stdout) = (io::stdin(), io::stdout());
    let mut scan = Scanner::new(stdin.lock());
    let mut out = io::BufWriter::new(stdout.lock());
    solve(&mut scan, &mut out);
}


#![allow(unused_imports)]
#![allow(unused_macros)]
#![allow(dead_code)]

use std::char::*;
use std::cmp::*;
use std::collections::*;
use std::io::*;
use std::str::FromStr;

macro_rules! debug {($($a:expr),*) => {println!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);}}
macro_rules! input { ( source = $ s : expr , $ ( $ r : tt ) * ) => { let mut iter = $ s . split_whitespace ( ) ; let mut next = || { iter . next ( ) . unwrap ( ) } ; input_inner ! { next , $ ( $ r ) * } } ; ( $ ( $ r : tt ) * ) => { let stdin = std :: io :: stdin ( ) ; let mut bytes = std :: io :: Read :: bytes ( std :: io :: BufReader :: new ( stdin . lock ( ) ) ) ; let mut next = move || -> String { bytes . by_ref ( ) . map ( | r | r . unwrap ( ) as char ) . skip_while ( | c | c . is_whitespace ( ) ) . take_while ( | c |! c . is_whitespace ( ) ) . collect ( ) } ; input_inner ! { next , $ ( $ r ) * } } ; }
macro_rules! input_inner { ( $ next : expr ) => { } ; ( $ next : expr , ) => { } ; ( $ next : expr , $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let $ var = read_value ! ( $ next , $ t ) ; input_inner ! { $ next $ ( $ r ) * } } ; }
macro_rules! read_value { ( $ next : expr , ( $ ( $ t : tt ) ,* ) ) => { ( $ ( read_value ! ( $ next , $ t ) ) ,* ) } ; ( $ next : expr , [ $ t : tt ; $ len : expr ] ) => { ( 0 ..$ len ) . map ( | _ | read_value ! ( $ next , $ t ) ) . collect ::< Vec < _ >> ( ) } ; ( $ next : expr , chars ) => { read_value ! ( $ next , String ) . chars ( ) . collect ::< Vec < char >> ( ) } ; ( $ next : expr , usize1 ) => { read_value ! ( $ next , usize ) - 1 } ; ( $ next : expr , $ t : ty ) => { $ next ( ) . parse ::<$ t > ( ) . expect ( "Parse error" ) } ; }

fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().split_whitespace()
        .map(|e| e.parse().ok().unwrap()).collect()
}

use std::f64;

fn min<T: PartialOrd>(a:T, b:T) -> T {
    if a < b { a }
    else { b }
}

fn max<T: PartialOrd>(a:T, b:T) -> T {
    if a < b { b }
    else { a }
}

use std::hash::Hash;
fn inc<T: Hash+Ord>(map:&mut BTreeMap<T,i64>, key:T) {
    let count = map.entry(key).or_insert(0);
    *count += 1;
}

fn int(ch: char) -> i64 {
    return (ch as u8 - b'0') as i64
}

const MAX:usize = 100006;
const INF:i64 = std::i64::MAX;
const MOD:i64 = 1e9 as i64 + 7;

fn main() {
    input!{n:usize, a:[usize;3]};

    let mut dp = vec![-1;n+1];
    dp[0] = 0;

    for i in 0..n+1 {
        for j in 0..3 {
            if i < a[j] { continue; }
            if dp[i-a[j]] == -1 { continue; }
            dp[i] = max(dp[i], dp[i-a[j]]+1);
        }
    }
    //debug!(dp);

    println!("{}", dp[n]);
}

/*

長さ n のリボンを a,b,c のいずれかの長さにする。
このとき、最大のリボンの数を求める。

dp[i] := 長さ i のリボンを切れる最大の数
dp[i] = max(dp[i-a[j]]+1, j=0,1,2)

*


se std::io::{self, BufRead};

type Point = (i32, i32);
type Seg = (Point, Point);

fn cm(base: &Point, a: &Point, b: &Point) -> i32 {
    let debug = false;
    if debug { println!("base {:?}, a {:?}, b {:?}", base, a, b) }
    return (a.0 - base.0)*(b.1 - base.1) - (a.1 - base.1)*(b.0 - base.0);
}

fn inx(a: i32, b: i32, x: i32) -> bool {
    return (b >= a && x >= a && x <= b) || (b <= a && x <= a && x >= b);
}

fn ins(pa: &Point, pb: &Point, px: &Point) -> bool {
    return inx(pa.0, pb.0, px.0) && inx(pa.1, pb.1, px.1);
}

fn intersect(a: &Seg, b: &Seg) -> bool {
    let b0 = cm(&a.0, &a.1, &b.0);
    if b0 == 0 && ins(&a.0, &a.1, &b.0) { return true; }
    let b1 = cm(&a.0, &a.1, &b.1);
    if b1 == 0 && ins(&a.0, &a.1, &b.1) { return true; }
    let a0 = cm(&b.0, &b.1, &a.0);
    if a0 == 0 && ins(&b.0, &b.1, &a.0) { return true; }
    let a1 = cm(&b.0, &b.1, &a.1);
    if a1 == 0 && ins(&b.0, &b.1, &a.1) { return true; }
    return ((a0 > 0 && a1 < 0) || (a0 < 0 && a1 > 0))
        && ((b0 > 0 && b1 < 0) || (b0 < 0 && b1 > 0));
}

fn main() {
    let debug = false;
    let stdin: io::Stdin = io::stdin();
    let mut lines: io::Lines<io::StdinLock> = stdin.lock().lines();

    let next_line = lines.next()
        .unwrap() // Option<Result> { Some(Result), None }
        .unwrap(); // Result<String, io::Error> { Ok(String), Err(io::Error) }

    let square_a: Vec<_> = next_line
        .trim()
        .split(' ')
        .map(|n| {
            n.parse::<i32>().unwrap()
        })
        .collect();

    let next_line = lines.next()
        .unwrap() // Option<Result> { Some(Result), None }
        .unwrap(); // Result<String, io::Error> { Ok(String), Err(io::Error) }

    let square_b: Vec<_> = next_line
        .trim()
        .split(' ')
        .map(|n| {
            n.parse::<i32>().unwrap()
        })
        .collect();

    // any a inside b
    for a_i in 0..4 {
        let a = (square_a[2*a_i], square_a[2*a_i+1]);
        let mut left = false;
        let mut right = false;
        for i in 0..4 {
            let base = (square_b[2*i], square_b[2*i+1]);
            let j = (i+1) % 4;
            let b = (square_b[2*j], square_b[2*j+1]);
            let cmv = cm(&base, &b, &a);
            if cmv > 0 { left = true; }
            if cmv < 0 { right = true; }
        }
        if !left || !right {
            println!("YES");
            return;
        }
    }

    // any b inside a
    for b_i in 0..4 {
        let b = (square_b[2*b_i], square_b[2*b_i+1]);
        let mut left = false;
        let mut right = false;
        for i in 0..4 {
            let base = (square_a[2*i], square_a[2*i+1]);
            let j = (i+1) % 4;
            let a = (square_a[2*j], square_a[2*j+1]);
            let cmv = cm(&base, &a, &b);
            if cmv > 0 { left = true; }
            if cmv < 0 { right = true; }
        }
        if !left || !right {
            println!("YES");
            return;
        }
    }

    // check intersect
    for a_i in 0..4 {
        let a_a = (square_a[2*a_i], square_a[2*a_i+1]);
        let a_j = (a_i + 1) % 4;
        let a_b = (square_a[2*a_j], square_a[2*a_j+1]);
        let seg_a = (a_a, a_b);

        for i in 0..4 {
            let b_a = (square_b[2*i], square_b[2*i+1]);
            let j = (i+1) % 4;
            let b_b = (square_b[2*j], square_b[2*j+1]);
            let seg_b = (b_a, b_b);
            if intersect(&seg_a, &seg_b) {
                println!("YES");
                return;
            }
        }
    }

    println!("NO");
}


#![allow(unused_imports)]
use std::io::{self, BufRead};
use std::cmp::*;
use std::collections::*;

macro_rules! scan_to_vec {
    ($count:expr, $t:ty) => ({
        let mut result = Vec::new();
        let stdin = io::stdin();
        let mut handle = stdin.lock();

        for _ in 0..$count {
            let mut buffer = String::new();
            handle.read_line(&mut buffer)
                .expect("scan_to_vec: failed at `handle.read_line`.");
            result.push(buffer.trim().parse::<$t>()
                .expect("scan_to_vec: failed at `parse::<$t>`."));
        }
        result
    })
}

macro_rules! scan_line_to_vec {
    ($t:ty) => ({
        let mut result = Vec::new();
        let stdin = io::stdin();
        let mut handle = stdin.lock();
        let mut buffer = String::new();
        handle.read_line(&mut buffer)
            .expect("scan_line_to_vec: failed at `handle.read_line`.");

        for s in buffer.split_whitespace() {
            result.push(s.parse::<$t>()
                .expect("scan_line_to_vec: failed at `parse::<$t>`."));
        }
        result
    })
}

macro_rules! scan_line {
    () => ({
        let stdin = io::stdin();
        let mut handle = stdin.lock();
        let mut buffer = String::new();
        handle.read_line(&mut buffer)
            .expect("scan_line: failed at `handle.read_line`.");
        buffer
    });
    ( $($t:ty)+ ) => ({
        let stdin = io::stdin();
        let mut handle = stdin.lock();
        let mut buffer = String::new();
        handle.read_line(&mut buffer)
            .expect("scan_line: failed at `handle.read_line`.");
        let mut chunks = buffer.split_whitespace();

        ($(
            {
                chunks.next()
                    .expect("scan_line: failed at `next`, # of space separated strings not equal to requested #")
                .parse::<$t>()
                    .expect("scan_line: failed at `parse::<$t>`.")
            },
        )+)
    })
}

fn main() {
    let (mut k,) = scan_line!(i64);

    if k == 0 {
        println!("a");
        return;
    }

    let mut sums = vec![0i64; 100001];
    for i in 1..sums.len() {
        sums[i] = sums[i-1] + i;
    }

    let mut char_counts = vec![0; 300];
    for i in ('a' as usize)..('z' as usize) {
        let index = {
            let mut index = 0;
            for i in (1..sums.len()).rev() {
                if k >= sums[i] as i64 {
                    index = i;
                    break;
                }
            }
            index
        };
        k = k - (sums[index] as i64);
        char_counts[i as usize] = index + 1;
        if k == 0 { break; }
    }

    let mut result = String::new();
    for i in ('a' as usize)..('z' as usize) {
        if char_counts[i as usize] > 1 {
            for j in 0..char_counts[i as usize] {
                result.push((i as u8) as char);
            }
        }
    }

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


use proconio::input;
fn main() {
    input! {
        n: usize,
        q: [u32; n]
    }
    for qq in q {
        println!("{}", 2u64.pow(qq) - 1);
    }
}


//! ----------------------------------------------
//! Framework <https://github.com/vain0x/procon>
//!
//! See the bottom of file for solution.
//! ----------------------------------------------

#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Display, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;

/// Print values to standard error if debug mode.
#[allow(unused_macros)]
macro_rules! debug {
    ($($e:expr),*) => {
        #[cfg(debug_assertions)]
        $({
            let (e, mut err) = (stringify!($e), stderr());
            writeln!(err, "\x1B[33m{}\x1B[0m = {:?}", e, $e).unwrap()
        })*
    };
}

/// Read from standard input and parse each word.
/// - `read!(T, U, ..)` parses a line as a tuple of words.
/// - `read![[T]]` parses a line as an array of words.
/// - `read![..; N]` parses `N` lines, using `read!(..)` repeatedly.
#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

/// Read a line from standard input.
#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();

    #[allow(deprecated)]
    buf.trim_right().to_owned()
}

// -----------------------------------------------
// Solution
// -----------------------------------------------

fn main() {
    let (N, M, r) = read!(usize, usize, i64);
    let S = read![[i64]];
    let B = read![[i64]];

    let &min_s = S.iter().min().unwrap();
    let &max_b = B.iter().max().unwrap();

    println!(
        "{}",
        if min_s >= max_b {
            r
        } else {
            (r % min_s) + (r / min_s) * max_b
        }
    )
}


use std::io;
use std::cmp::{
    min,
    max
};

macro_rules! readln {
    () => {{
        use std::io;
        let mut buf = String::new();
        io::stdin().read_line(&mut buf).unwrap();
        buf.trim().to_string()
    }};
    ( $t:ty ) => {{
        let input = readln!();
        input.parse::<$t>().unwrap()
    }};
    ( $( $t:ty ),+ ) => {{
        let input = readln!();
        let mut input = input.split_whitespace();
        (
            $(
                input.next().unwrap().parse::<$t>().unwrap(),
            )+
        )
    }}
}

fn main() {
    let (nodes, edges) = readln!(i64, i64);

    let (min_isolated, max_isolated) = if edges == 0 {
        (nodes, nodes)
    } else {
        (
            if nodes % 2 == 0 {
                max(0, ((nodes + 1) / 2 - edges) * 2)
            } else {
                max(0, ((nodes + 1) / 2 - edges) * 2 - 1)
            },
            nodes - ((1.0 + (8.0 * edges as f64 + 1.0).sqrt()) / 2.0).ceil() as i32
        )
    };

    println!("{} {}", min_isolated, max_isolated);
}


use std::{ io::{ self, Write } };

fn solve<I: Iterator<Item = io::Result<String>>>(mut lines: I) -> Option<Vec<bool>> {
	let count: usize = lines.next()?.ok()?
		.parse().ok()?;

	(0..count).map(|_| {
		let mut key: usize = lines.next()?.ok()?
			.parse().ok()?;
		let doors: [_; 3] = lines.next()?.ok()?
			.split(' ')
			.map(str::parse)
			.collect::<Result<Vec<usize>, _>>().ok()?
			.try_into().ok()?;

		let mut opened: usize = 0;

		while opened < 3 {
			key = if key > 0 && key <= doors.len() {
				doors[key - 1]
			} else {
				break;
			};

			opened += 1;
		}

		Some(opened == 3)
	})
		.collect()
}

fn main() -> io::Result<()> {
	let mut stdout = io::BufWriter::new(io::stdout());
	let lines = io::stdin().lines();

	let result = solve(lines).unwrap();

	for case in result {
		stdout.write_all(if case { b"YES\n" } else { b"NO\n" })?;
	}

	Ok(())
}


#![feature(int_log)]
use std::io::stdin;

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

    stdin.read_line(&mut string).unwrap();

    let n = string.trim().parse::<usize>().unwrap();

    let mut nodes = 2u128.pow(n as u32) - 2;
    let mut re = 1;
    loop{
        let mut inner_re = 4;
        if nodes == 0{
            break;
        }

        let times = nodes.log2();
        for _ in 0..times{
            inner_re = inner_re * inner_re;
            if inner_re >  (1e9 as u128 + 7){
                inner_re = inner_re% (1e9 as u128 + 7)
            }
        }

        re = re * inner_re % (1e9 as u128 + 7);
        nodes = nodes - 2u128.pow(times);
    }
    println!("{}", re * 6 % (1e9 as u128 + 7))
}


use std::io;

fn main() {
    let mut a_str = String::new();
    io::stdin().read_line(&mut a_str).expect("");
    let mut num = a_str.split_whitespace()
        .map(|x| x.parse::<i32>().expect("parse error"))
        .collect::<Vec<i32>>();
     io::stdin().read_line(&mut a_str).expect("");
    let mut v = a_str.split_whitespace()
        .map(|x| x.parse::<i32>().expect("parse error"))
        .collect::<Vec<i32>>();

    let n = num[0];
    let k = num[1];

    let mut res = 0;
    v.sort().reverse();
    for i in &v {
        if k % i == 0 {
            res = k / i;
            break;
        }
    }
    println!("{}", res);

}


use std::io;

#[cfg(debug_assertions)]
macro_rules! debug_println {
    ($( $args:expr ),*) => { println!( $( $args ),* ); }
}

fn main() {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    let (l, p) = buf.chars().fold((0, 0), |mut cnt, v| {
        match v {
            '-' => cnt.0 += 1,
            'o' => cnt.1 += 1,
            _ => (),
        }
        cnt
    });
    debug_println!("{:?}", (l, p));
    println!("{}", if l % p == 0 { "YES" } else { "NO" });
}


use std::{io, process};

fn main() {
	let n: u8 = {
		let mut line = String::new();
		io::stdin().read_line(&mut line).unwrap();
		line.trim().parse().unwrap()
	};

	let mut a: Vec<u8> = {
		let mut line = String::new();
		io::stdin().read_line(&mut line).unwrap();
		line.trim().split(' ').map(|a| a.parse().unwrap()).collect()
	};

	a.sort();

	// remove duplicates
	let mut i = a.len() - 1;
	loop {
		for j in (0..a.len()).rev() {
			if i == j {
				continue;
			}
			if a[i] == a[j] {
				if i > j {
					a.remove(i);
					a.remove(j);
				} else {
					a.remove(j);
					a.remove(i);
				}
				i -= 1;
				break;
			}
		}

		if i == 0 {
			break;
		}
		i -= 1;
	}

	assert!(a.len() % 2 == 0);

	let mut pb0 = 0u32;
	for s in a
		.iter()
		.enumerate()
		.filter(|s| s.0 % 2 == 0)
		.map(|s| *s.1)
		.zip(a.iter().enumerate().filter(|s| s.0 % 2 == 1).map(|s| *s.1))
	{
		pb0 += s.1 as u32 - s.0 as u32;
	}

	if a.len() < 3 {
		println!("{}", pb0);
		process::exit(0);
	}

	let mut pb1 = 0u32;
	let mut b: Vec<u8> = a
		.iter()
		.enumerate()
		.filter(|s| s.0 % 2 == 0)
		.map(|s| *s.1)
		.collect();
	println!("{:?}", b);
	b.remove(0);
	b.remove(b.len() - 1);
	for s in a
		.iter()
		.enumerate()
		.filter(|s| s.0 % 2 == 1)
		.map(|s| *s.1)
		.zip(b)
	{
		pb1 += s.1 as u32 - s.0 as u32;
	}
	pb1 += a[a.len() - 1] as u32 - a[0] as u32;

	println!("{}", pb0.min(pb1));
}


use std::io;

fn main() {
	let n: u8 = {
		let mut line = String::new();
		io::stdin().read_line(&mut line).unwrap();
		line.trim().parse().unwrap()
	};

	let mut a: Vec<u8> = {
		let mut line = String::new();
		io::stdin().read_line(&mut line).unwrap();
		line.trim().split(' ').map(|a| a.parse().unwrap()).collect()
	};

	a.sort();

	// remove duplicates
	let mut i = a.len() - 1;
	loop {
		for j in (0..a.len()).rev() {
			if i == j {
				continue;
			}
			if a[i] == a[j] {
				if i > j {
					a.remove(i);
					a.remove(j);
				} else {
					a.remove(j);
					a.remove(i);
				}
				i -= 1;
				break;
			}
		}

		if i == 0 {
			break;
		}
		i -= 1;
	}

	assert!(a.len() % 2 == 0);

	let mut pb0 = 0u32;
	for s in a.iter().enumerate().filter(|s| s.0 % 2 == 0).map(|s| *s.1).zip(a.iter().enumerate().filter(|s| s.0 % 2 == 1).map(|s| *s.1)) {
		pb0 += s.1 as u32 - s.0 as u32;
	}

	if a.len() < 3 {
		println!("{}", pb0);
		std::process::exit(0);
	}

	let mut pb1 = 0u32;
	let mut b: Vec<u8> = a.iter().enumerate().filter(|s| s.0 % 2 == 0).map(|s| *s.1).collect();
	println!("{:?}", b);
	b.remove(0);
	b.remove(b.len() - 1);
	for s in a.iter().enumerate().filter(|s| s.0 % 2 == 1).map(|s| *s.1).zip(b) {
		pb1 += s.1 as u32 - s.0 as u32;
	}
	pb1 += a[a.len() - 1] as u32 - a[0] as u32;

	println!("{}", pb0.min(pb1));
}


use std::{
    io::{prelude::*, stdin, stdout, BufWriter},
    mem::swap,
};

const MOD: i64 = 1000000007;

fn main() {
    let std_in = stdin();
    let mut input = Scanner::new(std_in.lock());

    let std_out = stdout();
    let mut output = BufWriter::new(std_out.lock());

    let n: usize = input.token();

    let mut phi: Vec<usize> = (0..=n).collect();
    for i in 2..=n {
        if phi[i] == i {
            for j in (i..=n).step_by(i) {
                phi[j] -= phi[j] / i;
            }
        }
    }

    let mut result = 0;
    for c in 1..n {
        let sum = n - c;
        if sum < 2 {
            continue;
        }

        add_to_result(c as i64, 1, phi[sum] as i64, &mut result);
        for x in 2..=sum {
            if x * x > sum {
                break;
            }
            if sum % x != 0 {
                continue;
            }

            let y = sum / x;
            if phi[y] != 0 {
                add_to_result(c as i64, x as i64, phi[y] as i64, &mut result);
            }
            if x != y && phi[x] != 0 {
                add_to_result(c as i64, y as i64, phi[x] as i64, &mut result);
            }
        }
    }
    writeln!(output, "{}", result).unwrap();
}

fn add_m(x: i64, y: i64) -> i64 {
    let mut tmp = x + y;
    if tmp < 0 {
        tmp += MOD;
    }
    if tmp >= MOD {
        tmp -= MOD;
    }
    tmp
}

fn mul_m(x: i64, y: i64) -> i64 {
    (x * y) % MOD
}

fn gcd(mut a: i64, mut b: i64) -> i64 {
    while b != 0 {
        a %= b;
        swap(&mut a, &mut b);
    }
    a
}

fn add_to_result(c: i64, g: i64, cnt: i64, result: &mut i64) {
    *result = add_m(*result, mul_m(cnt, c * g / gcd(c, g)));
}


use std::io;

const BALLS_SIZE: usize = 3;
const CRYST_SIZE: usize = 2;

enum ColorsC{
    Yell,
    Blue
}

enum ColorsB{
    Yell,
    Green,
    Blue
}

type CrystalsArray =  [i64; CRYST_SIZE];
type BallsArray = [i64; BALLS_SIZE];

fn count_crystals(balls :BallsArray) -> CrystalsArray{
    fn count_yellow(num: i64 ) -> CrystalsArray {
        [2*num, 0]
    }
    fn count_green(num: i64 ) -> CrystalsArray {
        [num, num]
    }
    fn count_blue(num: i64 ) -> CrystalsArray {
        [0,3*num]
    }
    println!("");
    let mut res: CrystalsArray = [0; CRYST_SIZE];
    for (ind,i) in count_yellow(balls[ColorsB::Yell as usize]).iter().enumerate(){
        res[ind] += i;
    }
    for (ind,i) in count_green(balls[ColorsB::Green as usize]).iter().enumerate(){
        res[ind] += i;
    }

    for (ind,i) in count_blue(balls[ColorsB::Blue as usize]).iter().enumerate(){
        res[ind] += i;
    }
    return res ;
}

fn main() {
    let mut input: String = String::new();
    io::stdin().read_line(&mut input).expect("some error");
    let mut cryst_inp: CrystalsArray = [0; CRYST_SIZE];
    let mut balls_inp: BallsArray = [0; BALLS_SIZE];
    for (ind,i) in input.trim().split(char::is_whitespace).enumerate(){
        cryst_inp[ind] = i.trim().parse().expect("failed to parse");
    }
    input.clear();
    io::stdin().read_line(&mut input).expect("some error");
    for (ind,i) in input.trim().split(char::is_whitespace).enumerate(){
        balls_inp[ind] = i.trim().parse().expect("failed to parse");
    }
    let have_to = count_crystals(balls_inp);
    let mut sum = 0;
    for (ind,i) in  cryst_inp.iter().enumerate(){
        sum += have_to[ind] - i;
    }
    print!("{}", sum);
}


#![allow(unused_variables)]
#![allow(unused_must_use)]
use std::io::{self, prelude::*};

fn solve<R: BufRead, W: Write>(mut input: FastInput<R>, mut w: W) {
    let n = input.token();
    let k: usize = input.token();
    let mut c = vec![0usize; n];
    for x in c.iter_mut() {
        *x = input.token();
    }
    let a = c.iter().filter(|&&x| x == 0).count();

    let first_0 = |a, n, x| x;
    let first_1 = |a, n, x| a - x;
    let second_0 = |a, n, x| a - x;
    let second_1 = |a, n, x| n - a - second_0(a, n, x);
    let increase = |a, n, x| {
        let res = first_1(a, n, x) * second_0(a, n, x);
        (res + res) / n / (n - RatioMod::identity())
    };
    let decrease = |a, n, x| {
        let res = first_0(a, n, x) * second_1(a, n, x);
        (res + res) / n / (n - RatioMod::identity())
    };
    let same = |a, n, x| {
        let res = a * (a - RatioMod::identity())
            + (n - a) * (n - a - RatioMod::identity())
            + first_0(a, n, x) * second_0(a, n, x)
            + first_0(a, n, x) * second_0(a, n, x)
            + first_1(a, n, x) * second_1(a, n, x)
            + first_1(a, n, x) * second_1(a, n, x);
        res / n / (n - RatioMod::identity())
    };

    let into = |x| Ratio::from(MOD7::from(x as u32));
    let inc = |x| increase(into(a), into(n), into(x));
    let dec = |x| same(into(a), into(n), into(x));
    let eq = |x| decrease(into(a), into(n), into(x));

    let mut init: Matrix<RatioMod> = Matrix::new(1, a + 1);
    *init.elem_mut(0, a - c[..a].iter().sum::<usize>()) = RatioMod::identity();

    let mut transition: Matrix<RatioMod> = Matrix::new(a + 1, a + 1);
    *transition.elem_mut(0, 0) = dec(0);
    if a > 0 {
        *transition.elem_mut(1, 0) = eq(1);
        *transition.elem_mut(a - 1, a) = inc(a - 1);
        *transition.elem_mut(a, a) = dec(a);
    }
    for i in 1..a {
        *transition.elem_mut(i - 1, i) = inc(i - 1);
        *transition.elem_mut(i, i) = dec(i);
        *transition.elem_mut(i + 1, i) = eq(i + 1);
    }
    let ans = init * binary_power(&transition, k as u64);
    let ans = ans.elem(0, a);
    let ans = ans.0 * ans.1.inverse();
    write!(w, "{}\n", ans);
}

fn main() {
    let stdin = io::stdin();
    let stdout = io::stdout();
    let input = FastInput::from(stdin.lock());
    let writer = io::BufWriter::new(stdout.lock());
    solve(input, writer);
}

trait TokenStream<T> {
    fn token(&mut self) -> T;
}

struct FastInput<R> {
    stdin: R,
    pos: usize,
}

impl<R: BufRead> From<R> for FastInput<R> {
    fn from(r: R) -> Self {
        FastInput { stdin: r, pos: 0 }
    }
}

impl<R: BufRead> TokenStream<u8> for FastInput<R> {
    fn token(&mut self) -> u8 {
        loop {
            if let Ok(buf) = self.stdin.fill_buf() {
                while self.pos < buf.len() {
                    self.pos += 1;
                    if buf[self.pos - 1] > 32 {
                        return buf[self.pos - 1];
                    }
                }
                if self.pos == 0 {
                    return 0;
                }
            } else {
                return 0;
            }
            self.stdin.consume(self.pos);
            self.pos = 0;
        }
    }
}

impl<R: BufRead> TokenStream<Vec<u8>> for FastInput<R> {
    fn token(&mut self) -> Vec<u8> {
        let mut ans = Vec::new();
        let mut parse_token = false;
        loop {
            if let Ok(buf) = self.stdin.fill_buf() {
                if !parse_token {
                    while self.pos < buf.len() && buf[self.pos] <= 32 {
                        self.pos += 1;
                    }
                }
                while self.pos < buf.len() && buf[self.pos] > 32 {
                    parse_token = true;
                    ans.push(buf[self.pos]);
                    self.pos += 1;
                }
                if self.pos != buf.len() || self.pos == 0 {
                    return ans;
                }
            }
            self.stdin.consume(self.pos);
            self.pos = 0;
        }
    }
}

macro_rules! impl_token_stream_u {
    ($($t:ident),+) => {$(
        impl<R: BufRead> TokenStream<$t> for FastInput<R> {
           fn token(&mut self) -> $t {
                let mut ans = 0;
                let mut parse_token = false;
                loop {
                    if let Ok(buf) = self.stdin.fill_buf() {
                        if !parse_token {
                            while self.pos < buf.len() && buf[self.pos] <= 32 {
                                self.pos += 1;
                            }
                        }
                        while self.pos < buf.len() && buf[self.pos] > 32 {
                            parse_token = true;
                            ans = ans * 10 + (buf[self.pos] - b'0') as $t;
                            self.pos += 1;
                        }
                        if self.pos != buf.len() || self.pos == 0 {
                            return ans;
                        }
                    }
                    self.stdin.consume(self.pos);
                    self.pos = 0;
                }
           }
        }
    )+}
}

pub trait Identity {
    fn identity() -> Self;
}

pub trait SelfIdentity {
    fn self_identity(&self) -> Self;
}

impl<T: Identity> SelfIdentity for T {
    fn self_identity(&self) -> Self {
        Self::identity()
    }
}

pub trait Inverse {
    fn inverse(self) -> Self;
}

macro_rules! define_modular_type {
    ($mod:ident, $value:expr) => {
        #[derive(Copy, Clone, Default, PartialEq)]
        struct $mod(u32);

        impl $mod {
            const MOD: u64 = $value;
        }

        impl std::fmt::Debug for $mod {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(f, "{:?}", self.0)
            }
        }

        impl std::fmt::Display for $mod {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(f, "{}", self.0)
            }
        }

        impl<T: Into<u64>> From<T> for $mod {
            fn from(a: T) -> Self {
                $mod((a.into() % Self::MOD) as u32)
            }
        }

        impl Into<u32> for $mod {
            fn into(self) -> u32 {
                self.0
            }
        }

        impl Identity for $mod {
            fn identity() -> Self {
                1u32.into()
            }
        }

        impl Inverse for $mod {
            fn inverse(self) -> Self {
                let mut t = (Self::default(), Self::identity());
                let mut r = (Self::MOD, self.0 as u64);
                while r.1 != 0 {
                    let q = r.0 / r.1;
                    t = (t.1, t.0 - t.1 * q.into());
                    r = (r.1, r.0 - r.1 * q);
                }
                t.0
            }
        }

        impl std::ops::Add for $mod {
            type Output = $mod;
            fn add(self, rhs: $mod) -> Self::Output {
                let mut ret = self.0 + rhs.0;
                if ret >= Self::MOD as u32 {
                    ret -= Self::MOD as u32;
                }
                $mod(ret)
            }
        }

        impl std::ops::AddAssign for $mod {
            fn add_assign(&mut self, rhs: Self) {
                self.0 += rhs.0;
                if self.0 >= Self::MOD as u32 {
                    self.0 -= Self::MOD as u32;
                }
            }
        }

        impl std::ops::Neg for $mod {
            type Output = Self;
            fn neg(self) -> Self::Output {
                $mod(Self::MOD as u32 - self.0)
            }
        }

        impl std::ops::Sub for $mod {
            type Output = $mod;
            fn sub(self, rhs: Self) -> Self::Output {
                if self.0 < rhs.0 {
                    $mod(self.0 + (Self::MOD as u32) - rhs.0)
                } else {
                    $mod(self.0 - rhs.0)
                }
            }
        }

        impl std::ops::SubAssign for $mod {
            fn sub_assign(&mut self, rhs: Self) {
                if self.0 < rhs.0 {
                    self.0 += Self::MOD as u32;
                }
                self.0 -= rhs.0
            }
        }

        impl std::ops::Mul for $mod {
            type Output = $mod;
            fn mul(self, rhs: Self) -> Self::Output {
                let a = self.0 as u64;
                let b = rhs.0 as u64;
                let c = a * b % Self::MOD;
                $mod(c as u32)
            }
        }

        impl std::ops::MulAssign for $mod {
            fn mul_assign(&mut self, rhs: Self) {
                *self = *self * rhs;
            }
        }

        impl std::ops::Div for $mod {
            type Output = Self;
            fn div(self, rhs: Self) -> Self::Output {
                self * rhs.inverse()
            }
        }

        impl std::ops::DivAssign for $mod {
            fn div_assign(&mut self, rhs: Self) {
                *self = *self / rhs;
            }
        }
    };
}

fn gcd<T>(mut a: T, mut b: T) -> T
where
    T: Copy + std::cmp::PartialEq + std::default::Default + std::ops::Rem<Output = T>,
{
    while b != T::default() {
        let r = a % b;
        a = b;
        b = r;
    }
    a
}

#[derive(Copy, Clone, Debug)]
struct Ratio<T>(T, T);

impl<T> Ratio<T>
where
    T: Copy
        + std::cmp::PartialEq
        + std::default::Default
        + std::ops::Rem<Output = T>
        + std::ops::DivAssign,
{
    fn normalize(&mut self) {
        let g = gcd(self.0, self.1);
        self.0 /= g;
        self.1 /= g;
    }
}

impl<T> std::default::Default for Ratio<T>
where
    T: std::default::Default + Identity,
{
    fn default() -> Self {
        Self(T::default(), T::identity())
    }
}

impl<T> Identity for Ratio<T>
where
    T: Identity,
{
    fn identity() -> Self {
        Self(T::identity(), T::identity())
    }
}

impl<T> From<(T, T)> for Ratio<T> {
    fn from(a: (T, T)) -> Self {
        Ratio(a.0, a.1)
    }
}

impl<T> From<T> for Ratio<T>
where
    T: Identity,
{
    fn from(a: T) -> Self {
        Ratio(a, T::identity())
    }
}

impl<T> std::ops::Add for Ratio<T>
where
    T: Copy + std::ops::Add<Output = T> + std::ops::Mul<Output = T>,
{
    type Output = Ratio<T>;
    fn add(self, rhs: Ratio<T>) -> Self::Output {
        Ratio(self.0 * rhs.1 + self.1 * rhs.0, self.1 * rhs.1)
    }
}

impl<T> std::ops::AddAssign for Ratio<T>
where
    T: Copy + std::ops::Add<Output = T> + std::ops::Mul<Output = T>,
{
    fn add_assign(&mut self, rhs: Ratio<T>) {
        let den = self.1 * rhs.1;
        self.0 = self.0 * rhs.1 + self.1 * rhs.0;
        self.1 = den;
    }
}

impl<T> std::ops::Sub for Ratio<T>
where
    T: Copy + std::ops::Sub<Output = T> + std::ops::Mul<Output = T>,
{
    type Output = Ratio<T>;
    fn sub(self, rhs: Ratio<T>) -> Self::Output {
        Ratio(self.0 * rhs.1 - self.1 * rhs.0, self.1 * rhs.1)
    }
}

impl<T> std::ops::Mul for Ratio<T>
where
    T: std::ops::Mul<Output = T>,
{
    type Output = Ratio<T>;
    fn mul(self, rhs: Ratio<T>) -> Self::Output {
        Ratio(self.0 * rhs.0, self.1 * rhs.1)
    }
}
impl<T> std::ops::MulAssign for Ratio<T>
where
    T: std::ops::MulAssign,
{
    fn mul_assign(&mut self, rhs: Ratio<T>) {
        self.0 *= rhs.0;
        self.1 *= rhs.1;
    }
}

impl<T> std::ops::Div for Ratio<T>
where
    T: std::ops::Mul<Output = T>,
{
    type Output = Ratio<T>;
    fn div(self, rhs: Ratio<T>) -> Self::Output {
        Ratio(self.0 * rhs.1, self.1 * rhs.0)
    }
}

#[derive(Clone)]
pub struct Matrix<T> {
    data: Vec<T>,
    cols: usize,
    rows: usize,
}

impl<T> Matrix<T>
where
    T: std::default::Default + Clone,
{
    pub fn new(rows: usize, cols: usize) -> Matrix<T> {
        let data = vec![T::default(); cols * rows];
        Matrix {
            data: data,
            cols: cols,
            rows: rows,
        }
    }
}

impl<T> Matrix<T> {
    pub fn rows(&self) -> std::slice::Chunks<T> {
        self.data.chunks(self.cols)
    }
    pub fn rows_mut(&mut self) -> std::slice::ChunksMut<T> {
        self.data.chunks_mut(self.cols)
    }
    pub fn elem(&self, row: usize, col: usize) -> &T {
        &self.data[self.cols * row + col]
    }
    pub fn elem_mut(&mut self, row: usize, col: usize) -> &mut T {
        &mut self.data[self.cols * row + col]
    }
}

impl<T> std::fmt::Debug for Matrix<T>
where
    T: std::fmt::Debug,
{
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.rows()
            .try_for_each(|row| fmt.write_fmt(format_args!("{:?}\n", row)))
    }
}

impl<T> SelfIdentity for Matrix<T>
where
    T: Identity + std::default::Default + Clone,
{
    fn self_identity(&self) -> Self {
        assert_eq!(self.cols, self.rows);
        let mut ret = Matrix::new(self.rows, self.cols);
        for (i, row) in ret.rows_mut().enumerate() {
            row[i] = T::identity();
        }
        ret
    }
}

impl<T> std::ops::Add for Matrix<T>
where
    T: Clone + std::default::Default + std::ops::Add<Output = T>,
{
    type Output = Matrix<T>;
    fn add(self, rhs: Matrix<T>) -> Matrix<T> {
        assert_eq!(self.cols, rhs.cols);
        assert_eq!(self.rows, rhs.rows);
        Matrix {
            data: self
                .data
                .iter()
                .zip(rhs.data)
                .map(|(a, b)| a.clone() + b.clone())
                .collect(),
            rows: self.rows,
            cols: self.cols,
        }
    }
}
impl<T> std::ops::Sub for Matrix<T>
where
    T: Clone + std::default::Default + std::ops::Sub<Output = T>,
{
    type Output = Matrix<T>;
    fn sub(self, rhs: Matrix<T>) -> Matrix<T> {
        assert_eq!(self.cols, rhs.cols);
        assert_eq!(self.rows, rhs.rows);
        Matrix {
            data: self
                .data
                .iter()
                .zip(rhs.data)
                .map(|(a, b)| a.clone() - b.clone())
                .collect(),
            rows: self.rows,
            cols: self.cols,
        }
    }
}
impl<T> std::ops::Mul for Matrix<T>
where
    T: Clone + std::default::Default + std::ops::AddAssign + std::ops::Mul<Output = T>,
{
    type Output = Matrix<T>;
    fn mul(self, rhs: Matrix<T>) -> Matrix<T> {
        assert_eq!(self.cols, rhs.rows);
        let mut ret: Matrix<T> = Matrix::new(self.rows, rhs.cols);
        for (ret_row, self_row) in ret.rows_mut().zip(self.rows()) {
            for (rhs_row, self_el) in rhs.rows().zip(self_row) {
                for (ret_el, rhs_el) in ret_row.iter_mut().zip(rhs_row) {
                    *ret_el += self_el.clone() * rhs_el.clone();
                }
            }
        }
        ret
    }
}

fn binary_power<T>(a: &T, mut exp: u64) -> T
where
    T: Clone + std::ops::Mul<Output = T> + SelfIdentity,
{
    let mut base = a.clone();
    let mut acc = a.self_identity();
    while exp > 1 {
        if (exp & 1) == 1 {
            acc = acc * base.clone();
        }
        exp /= 2;
        base = base.clone() * base.clone();
    }
    if exp == 1 {
        acc = acc * base;
    }
    acc
}

impl_token_stream_u!(usize);
define_modular_type!(MOD7, 1_000_000_007);
type RatioMod = Ratio<MOD7>;


use std::io;
use std::cmp;
use std::collections::HashMap;
fn read_i32s() -> io::Result<Vec<i32>> {
	let mut input = String::new();
	io::stdin().read_line(&mut input)?;
	let mut vec: Vec<i32> = Vec::new();
	for num in input.split_whitespace() {
		vec.push(num.parse::<i32>().unwrap());
	}
	return Ok(vec);
}

fn main() {
	let vec = read_i32s().unwrap();
	let _n = vec[0];
	let vec = read_i32s().unwrap();
	let mut cnt = HashMap::new();
	let mut mx = 0;
	for num in vec {
		let count = cnt.entry(num).or_insert(0);
		*count += 1;
		mx = cmp::max(mx, num);
	}
	let ans1 = mx;
	let mut t = 1;
	loop {
		if t*t > mx {
			break;
		}
		if mx % t == 0 {
			let count = cnt.entry(t).or_insert(0);
			if t*t == mx {
				break;
			}
			*count -= 1;
			let count = cnt.entry(mx/t).or_insert(0);
			*count -= 1;
		}
		t += 1;
	}
	mx = 0;
	for (key, value) in cnt.iter() {
		if *value != 0 {
			mx = cmp::max(mx, *key);
		}
	}
	let ans2 = mx;
	println!("{} {}", ans1, ans2);
}


use std::str::FromStr;
use std::io::stdin;

fn get_vals<T>(count: usize) -> Vec<T> where
    T: FromStr,
    <T as std::str::FromStr>::Err: std::fmt::Debug {
    let mut val = String::new();
    stdin().read_line(&mut val).expect("Failed to read line");
    val.split_whitespace()
        .map(|x|
            x.parse::<T>().expect("Failed to parse value"))
        .take(count).collect()
}

pub fn mashmokh() {
    let mut ins = get_vals::<usize>(2);
    let (n, k) = (ins.remove(0), ins.remove(0));
    let mut dp = vec![vec![0 as u32; k]; n];
    for x in dp[0].iter_mut() {
        *x = 1;
    }
    for i in dp.iter_mut() {
        i[0] = 1;
    }
    for i in 1..dp.len() {
        for j in 1..dp[i].len() {
            dp[i][j] = factor(i as i64 + 1)
                .into_iter()
                .map(|x| dp[x as usize - 1][j - 1])
                .sum()
        }
    }
    let ans: u32 = dp.iter_mut().map(|x| x[(k - 1) as usize]).sum();
    for i in dp {
        for j in i {
            print!("{0: <2}", j);
        }
        println!();
    }
    println!("{}", ans % 1000000007)
}

pub fn factor(input: i64) -> Vec<i64> {
    let mut vector = vec![];

    for count in 1..(input + 1) {
        if input % count == 0 {
            vector.push(count);
        }
    }

    return vector;
}