#![allow(unused)] #![allow(unstable_name_collisions)] extern crate proconio; use std::{ cmp::{Ordering, Reverse}, collections::{BinaryHeap, HashMap, HashSet, VecDeque, BTreeSet, BTreeMap}, iter::Copied, marker::PhantomData, mem::swap, ops::{Add, Shr}, fmt::{Display, Debug}, }; use ::{ proconio::{input, marker::{Chars, Usize1}, source::Readable}, // ac_library::{ModInt998244353 as Mint, Dsu, SccGraph}, // amplify::{map, set}, // counter::Counter, // recur_fn::{RecurFn, recur_fn}, // regex::Regex, // itertools::{Itertools, iproduct}, // superslice::Ext as _, // nalgebra::{self as na, DMatrix}, // btreemultimap::{BTreeMultiMap, btreemultimap}, // memoise::{memoise, memoise_map}, }; fn main() -> Result<(), Box> { input! { n: u64, } ((n.saturating_sub(99) + 499) / 500).println(); Ok(()) } #[macro_export] macro_rules! println_exit { ($($arg:tt)*) => { { println!($($arg)*); std::process::exit(0) } }; } #[macro_export] macro_rules! all_eq { ($val:expr, $($vals:expr),*) => { $($val == $vals &&)* true }; } #[macro_export] macro_rules! multi_vec { [$val:expr; $len:expr] => { vec![$val; $len] }; [$val:expr; $len:expr, $($lens:expr),*] => { vec![multi_vec![$val; $($lens),*]; $len] }; } #[macro_export] macro_rules! vec_deque { ($elem:expr; $len:expr) => { vec![$elem; $len].into_iter().collect::>() }; ($($elem:expr),* $(,)?) => { [$($elem),*].into_iter().collect::>() } } #[macro_export] macro_rules! cmp { ($_:tt) => { true }; ($_0:tt, $_1:tt) => { true }; ($l1:tt, $l2:tt $op:tt $r:tt $($others:tt)*) => { $l1 $op $r && $l2 $op $r && cmp!($r $($others)*) }; ($l:tt $op:tt $r1:tt, $r2:tt $($others:tt)*) => { $l $op $r1 && $l $op $r2 && cmp!($r1, $r2 $($others)*) }; ($l:tt $op:tt $r:tt $($others:tt)*) => { $l $op $r && cmp!($r $($others)*) }; } trait OrdAsign where Self: Ord + Sized { fn chmax(&mut self, other: Self) -> bool { if other > *self { *self = other; true } else { false } } fn chmin(&mut self, other: Self) -> bool { if other < *self { *self = other; true } else { false } } } impl OrdAsign for T {} trait PartialOrdAsign where Self: PartialOrd + Sized { fn pchmax(&mut self, other: Self) -> bool { if other > *self { *self = other; true } else { false } } fn pchmin(&mut self, other: Self) -> bool { if other < *self { *self = other; true } else { false } } } impl PartialOrdAsign for T {} trait OrdInsert { fn insert_max(&mut self, x: T) -> bool; fn insert_min(&mut self, x: T) -> bool; } impl OrdInsert for Option { fn insert_max(&mut self, x: T) -> bool { if let Some(s) = self { s.chmax(x) } else { self.insert(x); true } } fn insert_min(&mut self, x: T) -> bool { if let Some(s) = self { s.chmin(x) } else { self.insert(x); true } } } // struct LenVec { t: PhantomData } // impl Readable for LenVec { // type Output = Vec; // fn read>(source: &mut S) -> Self::Output { // input! { // from source, // len: usize, // vec: [T; len], // } // vec // } // } trait YesNo { fn yesno(&self) -> &'static str; fn print_yesno(&self); } impl YesNo for bool { fn yesno(&self) -> &'static str { if *self { "Yes" } else { "No" } } fn print_yesno(&self) { println!("{}", self.yesno()); } } trait RevSort { fn rev_sort(&mut self); } impl RevSort for [T] { fn rev_sort(&mut self) { self.sort_by(|l, r| r.cmp(l)); } } trait Sorted: Sized + AsMut<[T]> { fn sorted(mut self) -> Self { self.as_mut().sort(); self } fn sorted_by(mut self, cmp: impl FnMut(&T, &T) -> Ordering) -> Self { self.as_mut().sort_by(cmp); self } fn sorted_by_key(mut self, cmp: impl FnMut(&T) -> K) -> Self { self.as_mut().sort_by_key(cmp); self } fn rev_sorted(mut self) -> Self { self.as_mut().rev_sort(); self } } impl> Sorted for V {} trait Flip { fn flip(&mut self); } impl Flip for bool { fn flip(&mut self) { *self = !*self; } } use bit::*; mod bit { use std::ops::{BitAnd, Shr, ShrAssign}; pub trait Bit: Sized + BitAnd + Eq + Copy + Shr + ShrAssign { fn zero() -> Self; fn one() -> Self; fn bit

(self, pos: P) -> bool where Self: Shr { (self >> pos) & Self::one() == Self::one() } fn bits(self) -> Bits { Bits::new(self) } } #[derive(Debug, Clone)] pub struct Bits { n: T } impl Bits { fn new(n: T) -> Self { Self {n} } } impl Iterator for Bits { type Item = bool; fn next(&mut self) -> Option { if self.n == T::zero() { return None } let ret = self.n & T::one() == T::one(); self.n >>= 1; Some(ret) } } macro_rules! impl_trait { ($($type:ty)*) => { $(impl Bit for $type { fn zero() -> Self { 0 } fn one() -> Self { 1 } })* }; } impl_trait!(u8 u16 u32 u64 u128 usize); } trait Print: Display { fn print(&self) { print!("{self}"); } fn println(&self) { println!("{self}"); } fn eprint(&self) { eprint!("{self}"); } fn eprintln(&self) { eprintln!("{self}"); } } impl Print for T {} trait DebugPrint: Debug { fn dprint(&self) { eprint!("{self:?}"); } fn dprintln(&self) { eprintln!("{self:?}"); } } impl DebugPrint for T {} use slice_ext::*; mod slice_ext { use std::{iter::FusedIterator, ptr::slice_from_raw_parts, slice}; pub trait SliceExt { fn array_windows(&self) -> ArrayWindows<'_, T, N>; fn array_chunks(&self) -> ArrayChunks<'_, T, N>; fn array_chunks_mut(&mut self) -> ArrayChunksMut<'_, T, N>; } impl SliceExt for [T] { #[inline] fn array_windows(&self) -> ArrayWindows<'_, T, N> { ArrayWindows::new(self) } #[inline] fn array_chunks(&self) -> ArrayChunks<'_, T, N> { ArrayChunks::new(self) } #[inline] fn array_chunks_mut(&mut self) -> ArrayChunksMut<'_, T, N> { ArrayChunksMut::new(self) } } struct IsNonZero; impl IsNonZero { const OK: () = assert!(N > 0, "window size must be non-zero"); } #[derive(Debug, Clone)] pub struct ArrayWindows<'a, T, const N: usize> { slice: &'a [T], } impl<'a, T, const N: usize> ArrayWindows<'a, T, N> { fn new(slice: &'a [T]) -> Self { let _ = IsNonZero::::OK; Self { slice } } } impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> { type Item = &'a [T; N]; fn next(&mut self) -> Option { if self.slice.len() < N { None } else { let ret = self.slice[..N].try_into().unwrap(); self.slice = &self.slice[1..]; Some(ret) } } fn count(self) -> usize where Self: Sized { self.len() } fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } fn nth(&mut self, n: usize) -> Option { if self.len() < n + 1 { self.slice = &[]; None } else { self.slice = &self.slice[n..]; self.next() } } } impl<'a, T, const N: usize> ExactSizeIterator for ArrayWindows<'a, T, N> { fn len(&self) -> usize { self.slice.len().saturating_sub(N - 1) } } impl<'a, T, const N: usize> DoubleEndedIterator for ArrayWindows<'a, T, N> { fn next_back(&mut self) -> Option { if self.slice.len() < N { None } else { let ret = self.slice[self.slice.len() - N..].try_into().unwrap(); self.slice = &self.slice[..self.slice.len() - 1]; Some(ret) } } fn nth_back(&mut self, n: usize) -> Option { if self.len() < n + 1 { self.slice = &[]; None } else { self.slice = &self.slice[..self.slice.len() - n]; self.next_back() } } } impl<'a, T, const N: usize> FusedIterator for ArrayWindows<'a, T, N> {} #[derive(Debug, Clone)] pub struct ArrayChunks<'a, T, const N: usize> { slice: &'a [T], rem: &'a [T], } impl<'a, T, const N: usize> ArrayChunks<'a, T, N> { fn new(slice: &'a [T]) -> Self { let _ = IsNonZero::::OK; let slice_size = slice.len() / N * N; let (slice, rem) = slice.split_at(slice_size); Self { slice, rem } } fn remainder(&self) -> &'a [T] { self.rem } } impl<'a, T, const N: usize> Iterator for ArrayChunks<'a, T, N> { type Item = &'a [T; N]; fn next(&mut self) -> Option { if self.slice.len() < N { None } else { let ret = self.slice[..N].try_into().unwrap(); self.slice = &self.slice[N..]; Some(ret) } } fn count(self) -> usize where Self: Sized { self.len() } fn nth(&mut self, n: usize) -> Option { if self.len() < n + 1 { self.slice = &[]; None } else { self.slice = &self.slice[N * n..]; self.next() } } fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } } impl<'a, T, const N: usize> ExactSizeIterator for ArrayChunks<'a, T, N> { fn len(&self) -> usize { self.slice.len() / N } } impl<'a, T, const N: usize> DoubleEndedIterator for ArrayChunks<'a, T, N> { fn next_back(&mut self) -> Option { if self.slice.len() < N { None } else { let (head, ret) = self.slice.split_at(self.slice.len() - N); self.slice = head; Some(ret.try_into().unwrap()) } } fn nth_back(&mut self, n: usize) -> Option { if self.len() < n + 1 { self.slice = &[]; None } else { self.slice = &self.slice[..self.slice.len() - N * n]; self.next_back() } } } impl<'a, T, const N: usize> FusedIterator for ArrayChunks<'a, T, N> {} #[derive(Debug)] pub struct ArrayChunksMut<'a, T, const N: usize> { slice: &'a mut [T], rem: &'a mut[T], } impl<'a, T, const N: usize> ArrayChunksMut<'a, T, N> { fn new(slice: &'a mut [T]) -> Self { let _ = IsNonZero::::OK; let slice_size = slice.len() / N * N; let (slice, rem) = slice.split_at_mut(slice_size); Self { slice, rem } } fn into_remainder(self) -> &'a mut[T] { self.rem } } impl<'a, T, const N: usize> Iterator for ArrayChunksMut<'a, T, N> { type Item = &'a mut[T; N]; fn next(&mut self) -> Option { if self.slice.len() < N { None } else { let slice = std::mem::take(&mut self.slice); let (ret, tail) = slice.split_at_mut(N); self.slice = tail; let ret = ret.try_into().unwrap(); Some(ret) } } fn count(self) -> usize where Self: Sized { self.len() } fn nth(&mut self, n: usize) -> Option { if self.len() < n + 1 { self.slice = &mut []; None } else { let slice = std::mem::take(&mut self.slice); self.slice = slice.split_at_mut(N * n).1; self.next() } } fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } } impl<'a, T, const N: usize> ExactSizeIterator for ArrayChunksMut<'a, T, N> { fn len(&self) -> usize { self.slice.len() / N } } impl<'a, T, const N: usize> DoubleEndedIterator for ArrayChunksMut<'a, T, N> { fn next_back(&mut self) -> Option { if self.slice.len() < N { None } else { let slice = std::mem::take(&mut self.slice); let (head, ret) = slice.split_at_mut(slice.len() - N); self.slice = head; let ret = ret.try_into().unwrap(); Some(ret) } } fn nth_back(&mut self, n: usize) -> Option { if self.len() < n + 1 { self.slice = &mut []; None } else { let slice = std::mem::take(&mut self.slice); let len = slice.len(); self.slice = &mut slice[..len - N * n]; self.next_back() } } } impl<'a, T, const N: usize> FusedIterator for ArrayChunksMut<'a, T, N> {} }