//такое же тупое решение как и slow, но расходует в 10 раз меньше процессорного времени и памяти
use io::{BufRead, Write};
use std::io;
use std::str::FromStr;

#[cfg(dprintln)]
#[allow(unused_macros)]
macro_rules! dprintln { ($( $args:expr ),*) => { eprintln!( $( $args ),* ); } }

#[cfg(not(dprintln))]
#[allow(unused_macros)]
macro_rules! dprintln {
  ($( $args:expr ),*) => {};
}

struct Scanner<I> {
  it: I,
}

impl<I: std::iter::Iterator<Item = String>> Scanner<I> {
  fn next<A: FromStr>(&mut self) -> A {
    if let Ok(x) = self.it.next().unwrap().parse::<A>() {
      x
    } else {
      panic!("parse failed")
    }
  }
}

const INF: usize = usize::MAX;

fn main() -> io::Result<()> {
  let stdin = io::stdin();
  let it = stdin.lock().lines().flat_map(|s| {
    s.unwrap()
      .split_whitespace()
      .map(|s| s.to_owned())
      .collect::<Vec<_>>()
      .into_iter()
  });
  let mut r = Scanner { it };
  let stdout = io::stdout();
  let mut o = io::BufWriter::with_capacity(1 << 20, stdout.lock());
  let n = r.next::<usize>();
  let mut amin = vec![vec![0usize]];
  let mut amax = vec![vec![0usize]];
  //dp (x, correct)
  let h = n / 10;
  for i in 1..=n {
    //number of experiments
    let mut bmin = vec![vec![INF; h + 2]; i + 1];
    let mut bmax = vec![vec![0usize; h + 2]; i + 1];
    for x in 0..i {
      for c in 0..i.min(h + 1) {
        let mn = amin[x][c];
        let mx = amax[x][c];
        for s in 0..2 {
          //scientist result
          let y = x + s;
          for r in 0..2 {
            //experiment result
            let d = if r == s { c + 1 } else { c };
            bmin[y][d] = bmin[y][d].min(mn + r);
            bmax[y][d] = bmax[y][d].max(mx + r);
          }
        }
      }
    }
    amin = bmin;
    amax = bmax;
  }
  for i in 0..=n {
    writeln!(o, "{} {}", amin[i][h], amax[i][h])?;
  }
  o.flush()
}
