#![allow(non_snake_case)] #[allow(unused_imports)] use crate::{arraylist::List, scanner::Scanner}; use crate::{geometry::fraction::Frac, primes::utils::divisors}; fn main() { let ret = calc(); println!("{}", ret); } fn calc() -> i64 { let mut scan = Scanner::new(); let n = scan.long(); let a = divisors(n); let b = a.map(|x| Frac::new(1, x)); let c = Frac::new(a.sum(), 1) / b.fold(Frac::zero(), |acc, x| (acc + x).reduced()); c.reduced().numer } pub mod arraylist { use std::ops::*; use std::slice::Iter; use std::fmt::Formatter; use std::iter::FromIterator; use crate::independent::integer::Num; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct List { pub data: Vec, } impl List { #[inline] pub fn new() -> List { List { data: vec![] } } #[inline] pub fn push(&mut self, item: T) { self.data.push(item); } } macro_rules! impl_idx { ($($tpe:ty, $t:ident [$($output:tt)+], $slf:ident, $index:ident, $f:expr),*) => { $(impl<$t> Index<$tpe> for List<$t> { type Output = $($output)+; #[inline] fn index(&$slf, $index: $tpe) -> &Self::Output {$f} })* $(impl<$t> Index<$tpe> for lst<$t> { type Output = $($output)+; #[inline] fn index(&$slf, $index: $tpe) -> &Self::Output {$f} })* } } macro_rules! impl_idx_mut { ($($tpe:ty, $slf:ident, $index:ident, $f:expr),*) => { $(impl IndexMut<$tpe> for List { #[inline] fn index_mut(&mut $slf, $index: $tpe) -> &mut Self::Output {$f} })* $(impl IndexMut<$tpe> for lst { #[inline] fn index_mut(&mut $slf, $index: $tpe) -> &mut Self::Output {$f} })* }; } macro_rules! impl_idx_slice { ($($tpe:ty),*) => { impl_idx!($($tpe, T [lst], self, i, self.as_slice(i)),*); impl_idx_mut!($($tpe, self, i, self.as_slice_mut(i)),*); }; } impl_idx! { isize, T [T], self, i, self.at(i), char, T [T], self, i, self.at(i as isize - 'a' as isize) } impl_idx_slice! { Range, RangeTo, RangeFrom, RangeFull, RangeInclusive, RangeToInclusive } impl_idx_mut! { isize, self, i, self.at_mut(i), char, self, i, self.at_mut(i as isize - 'a' as isize) } impl FromIterator for List { #[inline] fn from_iter>(iter: U) -> Self { List { data: iter.into_iter().collect(), } } } impl IntoIterator for List { type Item = T; type IntoIter = std::vec::IntoIter; #[inline] fn into_iter(self) -> std::vec::IntoIter { self.data.into_iter() } } macro_rules! impl_traits { ($($tpe:tt),*) => { $( impl std::fmt::Display for $tpe { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.iter().map(|x| format!("{}", x)).collect::>().join(" ")) } } impl std::fmt::Debug for $tpe { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.data.fmt(f) } } impl<'a, T> IntoIterator for &'a $tpe { type Item = &'a T; type IntoIter = Iter<'a, T>; #[inline] fn into_iter(self) -> Iter<'a, T> { self.iter() } } )* }; } impl_traits!(List, lst); impl From> for List { #[inline] fn from(vec: Vec) -> Self { List { data: vec } } } impl From<&[T]> for List { #[inline] fn from(slice: &[T]) -> Self { slice.iter().cloned().collect() } } impl Deref for List { type Target = lst; #[inline] fn deref(&self) -> &lst { lst::new(&self.data) } } impl DerefMut for List { #[inline] fn deref_mut(&mut self) -> &mut lst { lst::new_mut(&mut self.data) } } #[macro_export] macro_rules! list { () => { $crate::arraylist::List::new() }; ($($v:expr),+ $(,)?) => { $crate::arraylist::List::from([$($v),+].to_vec()) }; ($v:expr; $a:expr) => { $crate::arraylist::List::init($v, $a)}; ($v:expr; $a:expr; $($rest:expr);+) => { $crate::arraylist::List::init(list!($v; $($rest);+), $a) }; } #[allow(non_camel_case_types)] #[derive(PartialEq, Eq, PartialOrd, Ord)] #[repr(transparent)] pub struct lst { data: [T], } impl lst { #[inline] pub fn new(slice: &[T]) -> &Self { unsafe { &*(slice as *const [T] as *const Self) } } #[inline] pub fn new_mut(slice: &mut [T]) -> &mut Self { unsafe { &mut *(slice as *mut [T] as *mut Self) } } #[inline] fn at(&self, index: isize) -> &T { if cfg!(debug_assertions) { self.data.index(index as usize) } else { unsafe { self.data.get_unchecked(index as usize) } } } #[inline] fn at_mut(&mut self, index: isize) -> &mut T { if cfg!(debug_assertions) { self.data.index_mut(index as usize) } else { unsafe { self.data.get_unchecked_mut(index as usize) } } } #[inline] pub fn as_slice(&self, range: impl RangeBounds) -> &lst { if cfg!(debug_assertions) { lst::new(self.data.index(self.rgm(range))) } else { unsafe { lst::new(self.data.get_unchecked(self.rgm(range))) } } } #[inline] pub fn as_slice_mut(&mut self, range: impl RangeBounds) -> &mut lst { if cfg!(debug_assertions) { lst::new_mut(self.data.index_mut(self.rgm(range))) } else { let r = self.rgm(range); unsafe { lst::new_mut(self.data.get_unchecked_mut(r)) } } } #[inline] pub fn cloned(&self) -> std::iter::Cloned> where T: Clone, { self.iter().cloned() } #[inline] pub fn map(&self, f: F) -> List where T: Clone, F: FnMut(T) -> B, { self.cloned().map(f).collect() } #[inline] pub fn fold(&self, init: B, f: F) -> B where T: Clone, F: FnMut(B, T) -> B, { self.cloned().fold(init, f) } #[inline] pub fn sum(&self) -> T where T: Num, { self.cloned().fold(T::zero(), |acc, x| acc + x) } #[inline] fn rgm(&self, r: impl RangeBounds) -> Range { (match r.start_bound() { Bound::Included(x) => *x as usize, Bound::Excluded(x) => *x as usize + 1, _ => 0, }) .max(0)..(match r.end_bound() { Bound::Included(x) => *x as usize + 1, Bound::Excluded(x) => *x as usize, _ => self.data.len(), }) .min(self.data.len()) } } impl lst {} impl Deref for lst { type Target = [T]; #[inline] fn deref(&self) -> &[T] { &self.data } } impl DerefMut for lst { #[inline] fn deref_mut(&mut self) -> &mut [T] { &mut self.data } } impl<'a, T> From<&'a [T]> for &'a lst { #[inline] fn from(slice: &'a [T]) -> Self { lst::new(slice) } } } pub mod geometry { pub mod fraction { use crate::{ impl_num_functions, independent::integer::{Int, Num}, }; use std::{ self, cmp::{Ordering, Ordering::*}, fmt::Display, ops::*, }; #[derive(Debug, Clone, Copy)] pub struct Frac { pub numer: T, pub denom: T, } impl Default for Frac { fn default() -> Self { Self::new_raw(T::zero(), T::one()) } } impl Display for Frac { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}/{}", self.numer, self.denom) } } impl PartialEq for Frac { fn eq(&self, other: &Self) -> bool { self.cmp(other) == Equal } } impl Eq for Frac {} impl Ord for Frac { fn cmp(&self, other: &Self) -> Ordering { if self.denom == other.denom { let ord = self.numer.cmp(&other.numer); return if self.denom < T::zero() { ord.reverse() } else { ord }; } if self.numer == other.numer { if self.numer == T::zero() { return Equal; } let ord = self.denom.cmp(&other.denom); return if self.numer < T::zero() { ord } else { ord.reverse() }; } if let Some((a, b)) = self .numer .cmul(other.denom) .and_then(|a| self.denom.cmul(other.numer).map(|b| (a, b))) { return a.cmp(&b); } let (self_int, self_rem) = self.div_mod_floor(); let (other_int, other_rem) = self.div_mod_floor(); match self_int.cmp(&other_int) { Greater => Greater, Less => Less, Equal => match (self_rem == T::zero(), other_rem == T::zero()) { (true, true) => Equal, (true, false) => Less, (false, true) => Greater, (false, false) => { let self_recip = Self::new_raw(self.denom, self_rem); let other_recip = Self::new_raw(other.denom, other_rem); self_recip.cmp(&other_recip).reverse() } }, } } } impl PartialOrd for Frac { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Frac { pub fn new_raw(numer: T, denom: T) -> Self { Self { numer, denom } } pub fn new(numer: T, denom: T) -> Self { if denom == T::zero() { panic!("denominator == 0") } if numer == T::zero() { return Self::new_raw(numer, T::one()); } Self::new_raw(numer, denom).reduced() } pub fn new_int(numer: T) -> Self { Self { numer, denom: T::one(), } } pub fn zero() -> Self { Self::new_raw(T::zero(), T::one()) } pub fn floor(&self) -> T { if *self < Self::zero() { (self.numer - self.denom + T::one()) / self.denom } else { self.numer / self.denom } } pub fn reduce(&mut self) { let g = gcd(self.numer, self.denom); self.numer /= g; self.denom /= g; if self.denom < T::zero() { self.numer = T::zero() - self.numer; self.denom = T::zero() - self.denom; } } pub fn reduced(&self) -> Self { let mut t = *self; t.reduce(); t } fn div_mod_floor(&self) -> (T, T) { if self.numer < T::zero() { ( T::zero() - (self.numer + self.denom - T::one()) / self.denom, self.denom + self.numer % self.denom, ) } else { (self.numer / self.denom, self.numer % self.denom) } } } fn gcd(a: T, b: T) -> T { if b == T::zero() { a } else { gcd(b, a % b) } } fn lcm(a: T, b: T) -> T { a / gcd(a, b) * b } impl Num for Frac { impl_num_functions! { |s: &Self| s.floor().to_i128(), |x| Self::new_int(T::from_i128(x as _)), |s: Self| if s < Self::zero() {-1} else if s > Self::zero() {1} else {0} } } impl AddAssign for Frac { fn add_assign(&mut self, other: Self) { if self.denom == other.denom { self.numer += other.numer } else { let lcm = lcm(self.denom, other.denom); let lhs_numer = self.numer * (lcm / self.denom); let rhs_numer = other.numer * (lcm / other.denom); self.numer = lhs_numer + rhs_numer; self.denom = lcm; } } } impl DivAssign for Frac { fn div_assign(&mut self, other: Self) { let gcd_ac = gcd(self.numer, other.numer); let gcd_bd = gcd(self.denom, other.denom); self.numer /= gcd_ac; self.numer *= other.denom / gcd_bd; self.denom /= gcd_bd; self.denom *= other.numer / gcd_ac; } } impl MulAssign for Frac { fn mul_assign(&mut self, other: Self) { let gcd_ad = gcd(self.numer, other.denom); let gcd_bc = gcd(self.denom, other.numer); self.numer /= gcd_ad; self.numer *= other.numer / gcd_bc; self.denom /= gcd_bc; self.denom *= other.denom / gcd_ad; } } impl RemAssign for Frac { fn rem_assign(&mut self, other: Self) { if self.denom == other.denom { self.numer %= other.numer } else { let lcm = lcm(self.denom, other.denom); let lhs_numer = self.numer * (lcm / self.denom); let rhs_numer = other.numer * (lcm / other.denom); self.numer = lhs_numer % rhs_numer; self.denom = lcm; } } } impl SubAssign for Frac { fn sub_assign(&mut self, other: Self) { if self.denom == other.denom { self.numer -= other.numer; } else { let lcm = lcm(self.denom, other.denom); let lhs_numer = self.numer * (lcm / self.denom); let rhs_numer = other.numer * (lcm / other.denom); self.numer = lhs_numer - rhs_numer; self.denom = lcm; } } } macro_rules! impl_ops { ($($tpe:ident, $fname:ident, $fname2:tt),*) => { $(impl $tpe for Frac { type Output = Self; fn $fname(self, other: Self) -> Self { let mut ret = self.clone(); ret $fname2 other; ret } })* }; } impl_ops!(Add, add, +=, Sub, sub, -=, Mul, mul, *=, Div, div, /=, Rem, rem, %=); } } pub mod independent { pub mod integer { use std::fmt::Debug; use std::fmt::Display; use std::ops::*; pub trait Num: Add + Sub + Mul + Div + AddAssign + SubAssign + MulAssign + DivAssign + PartialEq + PartialOrd + Copy + Debug + Display { fn to_u32(&self) -> u32; fn to_u64(&self) -> u64; fn to_u128(&self) -> u128; fn to_i32(&self) -> i32; fn to_i64(&self) -> i64; fn to_i128(&self) -> i128; fn to_usize(&self) -> usize; fn to_isize(&self) -> isize; fn to_f64(&self) -> f64; fn from_i32(x: i32) -> Self; fn from_u32(x: u32) -> Self; fn from_u64(x: u64) -> Self; fn from_u128(x: u128) -> Self; fn from_i64(x: i64) -> Self; fn from_i128(x: i128) -> Self; fn from_usize(x: usize) -> Self; fn from_isize(x: isize) -> Self; fn from_f64(x: f64) -> Self; fn zero() -> Self; fn one() -> Self; fn approx_sign(self) -> i32; fn approx_eq(self, other: Self) -> bool { (self - other).approx_sign() == 0 } } pub trait Int: Num + Rem + RemAssign + Ord { fn powint(&self, n: i64) -> Self; fn cmul(&self, b: Self) -> Option; } pub trait Float: Num {} #[macro_export] macro_rules! impl_num_functions { ($to_op:expr, $from_op:expr, $appx_op:expr) => { impl_num_functions!( $to_op, $from_op, to_u32, from_u32, u32, to_u64, from_u64, u64, to_u128, from_u128, u128, to_i32, from_i32, i32, to_i64, from_i64, i64, to_i128, from_i128, i128, to_usize, from_usize, usize, to_isize, from_isize, isize, to_f64, from_f64, f64 ); fn approx_sign(self) -> i32 {($appx_op)(self)} }; ($to_op:expr, $from_op:expr, $($tofn:ident, $fromfn:ident, $tpe:ident),*) => { $( fn $tofn(&self) -> $tpe { $to_op(self) as $tpe } fn $fromfn(x: $tpe) -> Self { $from_op(x) } )* fn zero() -> Self {$from_op(0)} fn one() -> Self {$from_op(1)} }; } macro_rules! impl_num_int { ($($tpe:ident),*) => { $( impl Num for $tpe { impl_num_functions!( |s: &Self| *s, |x| x as $tpe, |s: Self| if s < Self::zero() {-1} else if s > Self::zero() {1} else {0} ); } impl Int for $tpe { fn powint(&self, n: i64) -> Self { self.pow(n as u32) as $tpe } fn cmul(&self, b: Self) -> Option {self.checked_mul(b)} } )* }; } impl_num_int!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize); pub const EPS: f64 = 1e-6; impl Num for f64 { impl_num_functions!(|s: &Self| *s, |x| x as f64, |s: Self| if s < -EPS { -1 } else if s > EPS { 1 } else { 0 }); } impl Float for f64 {} } } pub mod primes { pub mod utils { use crate::arraylist::List; pub fn divisors(n: i64) -> List { let mut ret = List::new(); for i in (1..).take_while(|i| i * i <= n) { if n % i == 0 { ret.push(i); if i != n / i { ret.push(n / i); } } } ret } } } pub mod types { pub use crate::arraylist::List as Seq; #[allow(non_camel_case_types)] pub type idx = isize; pub use crate::list as seq; pub use std::collections::hash_map as map; pub use std::collections::HashMap as Map; } pub mod scanner { use std::io::{stdin, BufReader, Bytes, Read, Stdin}; use std::str::FromStr; pub struct Scanner { buf: Bytes>, } impl Scanner { pub fn new() -> Scanner { Scanner { buf: BufReader::new(stdin()).bytes(), } } #[inline] fn token>(&mut self) -> T { self.buf .by_ref() .map(|c| c.unwrap() as char) .skip_while(|c| c.is_whitespace()) .take_while(|c| !c.is_whitespace()) .collect() } #[inline] pub fn read(&mut self) -> T { self.string().parse().ok().unwrap() } #[inline] pub fn string(&mut self) -> String { self.token() } #[inline] pub fn long(&mut self) -> i64 { self.read() } } }