//spnauti-rusT {{{
use std::io::*; use std::str::{self,*}; use std::fmt::Debug;
#[allow(unused_imports)] use std::cmp::Ordering::{self,*};
#[allow(unused_imports)] use std::ops::{self,*};
#[allow(unused_imports)] use std::iter::{self,*};
#[allow(unused_imports)] use std::collections::*;
#[allow(unused_imports)] use std::cell::*;
#[allow(unused_macros)] macro_rules! min {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b < *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! max {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b > *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! l {
	($($v:ident),+ =$e:expr) => {$(let$v=$e;)+};
	($($v:ident),+:$t:ty=$e:expr) => {$(let$v:$t=$e;)+};
	(mut $($v:ident),+ =$e:expr) => {$(let mut$v=$e;)+};
	(mut $($v:ident),+:$t:ty=$e:expr) => {$(let mut$v:$t=$e;)+};
}
#[allow(unused_macros)] macro_rules! v {
	([$d:expr]$($s:tt)+) => {vec![v!($($s)+);$d]};
	([]) => {Vec::new()}; ([$e:expr]) => {Vec::with_capacity($e)}; (=$e:expr) => {$e};
}
#[allow(unused_macros)] macro_rules! rep { {[$c:expr]$($s:tt)+} => {for _ in 0..$c {$($s)+}} }
#[allow(dead_code)] fn reader() -> WordReaderC { WordReaderC::new() }
#[allow(dead_code)] fn writer() -> BufWriter<Stdout> { BufWriter::new(stdout()) }
struct WordReaderC {buf: Vec<u8>, pos: usize, q: std::io::StdinLock<'static>}//'
#[allow(dead_code)] impl WordReaderC {
	fn new() -> Self {
		let r = unsafe {&*Box::into_raw(Box::new(stdin()))};
		Self { q: r.lock(), buf: v!([]), pos: 0 }
	}
	fn next_line(&mut self) -> bool {
		self.buf.clear(); self.pos = 0;
		self.q.read_until(b'\n', &mut self.buf).unwrap_or(0) > 0
	}
	fn is_ws(c: u8) -> bool {
		c == b' ' || c == b'\r' || c == b'\n' || c == b'\t'
	}
	fn byte(&mut self) -> Option<u8> {
		if self.pos == self.buf.len() { if !self.next_line() { return None; } }
		self.pos += 1; Some(self.buf[self.pos - 1])
	}
	fn vb(&mut self) -> Vec<u8> {
		let mut s = v!([8]);
		let mut f = false;
		loop {
			if let Some(c) = self.byte() {
				if !Self::is_ws(c) {
					s.push(c);
					f = true;
				} else if f { break; }
			} else { break; }
		}
		s
	}
	fn board(&mut self, r: usize, c: Option<usize>) -> Vec<Vec<u8>> {
		let mut res = v!([r]);
		let c = c.unwrap_or(0);
		rep!{[r]
			let t = self.vb();
			assert!(c == 0 || t.len() == c);
			res.push(t);
		}
		res
	}
	fn framed_board(&mut self, r: usize, c: usize, f: u8) -> Vec<Vec<u8>> {
		let mut res = v!([r+2]);
		res.push( v!([c+2] = f) );
		rep!{[r]
			let mut t = self.vb();
			assert!(t.len() == c);
			t.reserve(2);
			t.insert(0,f);
			t.push(f);
			res.push(t);
		}
		res.push( v!([c+2] = f) );
		res
	}
	fn s(&mut self) -> String { String::from_utf8(self.vb()).expect("invalid utf8") }
	fn i(&mut self) ->    i32 { self.p() }
	fn l(&mut self) ->    i64 { self.p() }
	fn u(&mut self) ->  usize { self.p() }
	fn f(&mut self) ->    f64 { self.p() }
	fn vi(&mut self, n: usize) -> Vec<i32> { self.vp(n) }
	fn vl(&mut self, n: usize) -> Vec<i64> { self.vp(n) }
	fn vu(&mut self, n: usize) -> Vec<usize> { self.vp(n) }
	fn ii(&mut self, n: usize) -> impl Iterator<Item=i32> { self.ip(n).into_iter() }
	fn iu(&mut self, n: usize) -> impl Iterator<Item=usize> { self.ip(n).into_iter() }
	fn p<T: FromStr>(&mut self) -> T where T::Err: Debug {
		let w = self.vb(); str::from_utf8(w.as_ref()).unwrap().parse::<T>().unwrap()
	}
	fn vp<T: FromStr>(&mut self, n: usize) -> Vec<T> where T::Err: Debug {
		(0..n).map(|_|self.p()).collect()
	}
	fn ip<T: FromStr>(&mut self, n: usize) -> impl Iterator<Item=T> where T::Err: Debug {
		self.vp(n).into_iter()
	}
	fn graph(&mut self, n: usize, m: usize) -> Vec<Vec<usize>> {
		let mut e = v!([n][]); rep!{[m] l!(a,b = self.u()-1); e[a].push(b); e[b].push(a); } e
	}
	fn graph_w<T: Copy+FromStr>(&mut self, n: usize, m: usize) -> Vec<Vec<(usize,T)>> where T::Err: Debug {
		let mut e = v!([n][]); rep!{[m] l!(a,b = self.u()-1); let c: T = self.p(); e[a].push((b,c)); e[b].push((a,c)); } e
	}
}
//------------------- End rusT }}}

fn main() {
	let mut rin = reader();
	let mut rout = writer();

	l!(n,m,i,j,a,b = rin.i());
	let mut sol = None;
	for &(x,y) in [(1,1), (1,m), (n,1), (n,m)].iter() {
		if (x - i) % a == 0 && (y - j) % b == 0 {
			let xx = (x - i).abs() / a;
			let yy = (y - j).abs() / b;
			let mx = xx > 0 || a < n;
			let my = yy > 0 || b < m;
			if (xx == 0 && yy == 0) || (mx && my && (xx ^ yy) & 1 == 0) {
				let res = xx.max(yy).min(sol.unwrap_or(1000000000));
				sol.replace(res);
			}
		}
	}
	if let Some(ans) = sol {
		writeln!(rout, "{}", ans).ok();
	} else {
		writeln!(rout, "Poor Inna and pony!").ok();
	}
}


macro_rules! scanln {
    () => ({
        let mut buffer = String::new();
        ::std::io::stdin().read_line(&mut buffer).expect("Unable to read line");
        buffer
    });
    ($($t: ty),+) => ({
        scanln!($($t),+, |c: char| c.is_whitespace())
    });
    ($($t: ty),+, $sp: expr) => ({
        let mut buffer = scanln!();
        let mut iter = buffer.split($sp);
        ($(iter.next().unwrap().parse::<$t>().expect("Unable to parse token")),+)
    });
}

fn main() {
    const MOD: u64 = 1000000009;
    let mut dp = vec![[[[[0u64; 2]; 32]; 32]; 32]; 1001].into_boxed_slice();
    let (n, h) = scanln!(usize, usize);
    dp[0][0][0][0][0] = 1;

    for i in 1..=n {
        for a in 0..=(h + 1) {
            for b in a..=(h + 1) {
                for c in b..=(h + 1) {
                    for y in 0..2 {
                        dp[(i - 1) as usize][a][b][c][y] %= MOD;
                        let val = dp[(i - 1) as usize][a][b][c][y];
                        let ta = if a + 1 > h { h + 1 } else { a + 1 };
                        let tb = if b + 1 > h { h + 1 } else { b + 1 };
                        let tc = if c + 1 > h { h + 1 } else { c + 1 };
                        dp[i][ta][tb][tc][y] += val;
                        if y == 0 {
                            dp[i][1][tb][tc][(ta > h) as usize] += val;
                            dp[i][1][ta][tc][(tb > h) as usize] += val;
                            dp[i][1][ta][tb][(tc > h) as usize] += val;
                        } else {
                            dp[i][tb][tc][h + 1][(ta > h) as usize] += val;
                            dp[i][ta][tc][h + 1][(tb > h) as usize] += val;
                            dp[i][ta][tb][h + 1][(tc > h) as usize] += val;
                        }
                    }
                }
            }
        }
    }

    let mut res = 0;

    for a in 0..=(h + 1) {
        for b in a..=(h + 1) {
            for c in b..=(h + 1) {
                for y in 0..2 {
                    if (a < h) || (b < h) || (c < h) || (y == 0) {
                        res += dp[n][a][b][c][y];
                    }
                }
            }
        }
    }

    println!("{}", res % MOD);
}


#[allow(unused_imports)]
use std::io::{ BufWriter, stdin, stdout, Write, Stdout };

#[derive(Default)]
struct Scanner {
    buffer: Vec<String>
}
impl Scanner {
    fn next<T: std::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();
            stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

const DIG: [&'static str; 10] = [
    "O-|-OOOO",
    "O-|O-OOO",
    "O-|OO-OO",
    "O-|OOO-O",
    "O-|OOOO-",
    "-O|-OOOO",
    "-O|O-OOO",
    "-O|OO-OO",
    "-O|OOO-O",
    "-O|OOOO-",
];

fn main() {
    let out = &mut BufWriter::new(stdout());
    let mut n: usize = (Scanner::default()).next();
    let mut nums = vec![];
    if n == 0 {
        writeln!(out, "{}", DIG[0]).ok();
        return;
    }
    while n != 0 {
        nums.push(n % 10);
        n = n/10;
    }
    nums.iter().for_each(|d| {
        writeln!(out, "{}", DIG[*d]).ok();
    });
}


//spnauti-rusT {{{
use std::io::*; use std::str::{self,*}; use std::fmt::Debug;
#[allow(unused_imports)] use std::cmp::Ordering::{self,*};
#[allow(unused_imports)] use std::ops::{self,*};
#[allow(unused_imports)] use std::iter::{self,*};
#[allow(unused_imports)] use std::collections::*;
#[allow(unused_imports)] use std::cell::*;
#[allow(unused_macros)] macro_rules! min {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b < *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! max {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b > *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! l {
	($($v:ident),+ =$e:expr) => {$(let$v=$e;)+};
	($($v:ident),+:$t:ty=$e:expr) => {$(let$v:$t=$e;)+};
	(mut $($v:ident),+ =$e:expr) => {$(let mut$v=$e;)+};
	(mut $($v:ident),+:$t:ty=$e:expr) => {$(let mut$v:$t=$e;)+};
}
#[allow(unused_macros)] macro_rules! v {
	([$d:expr]$($s:tt)+) => {vec![v!($($s)+);$d]};
	([]) => {Vec::new()}; ([$e:expr]) => {Vec::with_capacity($e)}; (=$e:expr) => {$e};
}
#[allow(unused_macros)] macro_rules! rep { {[$c:expr]$($s:tt)+} => {for _ in 0..$c {$($s)+}} }
#[allow(dead_code)] fn reader() -> WordReaderC { WordReaderC::new() }
#[allow(dead_code)] fn writer() -> BufWriter<Stdout> { BufWriter::new(stdout()) }
struct WordReaderC {buf: Vec<u8>, pos: usize, q: std::io::StdinLock<'static>}//'
#[allow(dead_code)] impl WordReaderC {
	fn new() -> Self {
		let r = unsafe {&*Box::into_raw(Box::new(stdin()))};
		Self { q: r.lock(), buf: v!([]), pos: 0 }
	}
	fn next_line(&mut self) -> bool {
		self.buf.clear(); self.pos = 0;
		self.q.read_until(b'\n', &mut self.buf).unwrap_or(0) > 0
	}
	fn is_ws(c: u8) -> bool {
		c == b' ' || c == b'\r' || c == b'\n' || c == b'\t'
	}
	fn byte(&mut self) -> Option<u8> {
		if self.pos == self.buf.len() { if !self.next_line() { return None; } }
		self.pos += 1; Some(self.buf[self.pos - 1])
	}
	fn vb(&mut self) -> Vec<u8> {
		let mut s = v!([8]);
		let mut f = false;
		loop {
			if let Some(c) = self.byte() {
				if !Self::is_ws(c) {
					s.push(c);
					f = true;
				} else if f { break; }
			} else { break; }
		}
		s
	}
	fn board(&mut self, r: usize, c: Option<usize>) -> Vec<Vec<u8>> {
		let mut res = v!([r]);
		let c = c.unwrap_or(0);
		rep!{[r]
			let t = self.vb();
			assert!(c == 0 || t.len() == c);
			res.push(t);
		}
		res
	}
	fn framed_board(&mut self, r: usize, c: usize, f: u8) -> Vec<Vec<u8>> {
		let mut res = v!([r+2]);
		res.push( v!([c+2] = f) );
		rep!{[r]
			let mut t = self.vb();
			assert!(t.len() == c);
			t.reserve(2);
			t.insert(0,f);
			t.push(f);
			res.push(t);
		}
		res.push( v!([c+2] = f) );
		res
	}
	fn s(&mut self) -> String { String::from_utf8(self.vb()).expect("invalid utf8") }
	fn i(&mut self) ->    i32 { self.p() }
	fn l(&mut self) ->    i64 { self.p() }
	fn u(&mut self) ->  usize { self.p() }
	fn f(&mut self) ->    f64 { self.p() }
	fn vi(&mut self, n: usize) -> Vec<i32> { self.vp(n) }
	fn vl(&mut self, n: usize) -> Vec<i64> { self.vp(n) }
	fn vu(&mut self, n: usize) -> Vec<usize> { self.vp(n) }
	fn ii(&mut self, n: usize) -> impl Iterator<Item=i32> { self.ip(n).into_iter() }
	fn iu(&mut self, n: usize) -> impl Iterator<Item=usize> { self.ip(n).into_iter() }
	fn p<T: FromStr>(&mut self) -> T where T::Err: Debug {
		let w = self.vb(); str::from_utf8(w.as_ref()).unwrap().parse::<T>().unwrap()
	}
	fn vp<T: FromStr>(&mut self, n: usize) -> Vec<T> where T::Err: Debug {
		(0..n).map(|_|self.p()).collect()
	}
	fn ip<T: FromStr>(&mut self, n: usize) -> impl Iterator<Item=T> where T::Err: Debug {
		self.vp(n).into_iter()
	}
	fn graph(&mut self, n: usize, m: usize) -> Vec<Vec<usize>> {
		let mut e = v!([n][]); rep!{[m] l!(a,b = self.u()-1); e[a].push(b); e[b].push(a); } e
	}
	fn graph_w<T: Copy+FromStr>(&mut self, n: usize, m: usize) -> Vec<Vec<(usize,T)>> where T::Err: Debug {
		let mut e = v!([n][]); rep!{[m] l!(a,b = self.u()-1); let c: T = self.p(); e[a].push((b,c)); e[b].push((a,c)); } e
	}
}
//------------------- End rusT }}}

// Field (mod prime) {{{
mod field {
	use std::ops::*;
	#[allow(dead_code)] pub const Z0: Field = Field(0);
	#[allow(dead_code)] pub const Z1: Field = Field(1);
	const P5: i32 = 1_000_000_007;
	const P6: i64 = P5 as i64;
	#[derive(Debug,Clone,Copy,PartialEq,Eq,PartialOrd,Ord,Default)] pub struct Field(i32);
	#[allow(dead_code)] impl Field {
		pub fn new<T: Into<i64>>(a: T) -> Self { Self(Self::cv(a)) }
		pub fn new_unchecked(a: i32) -> Self { Self(a) }
		fn hi(mut a: i32) -> i32 { if a >= P5 { a -= P5; } a }
		fn lo(mut a: i32) -> i32 { if a < 0 { a += P5; } a }
		fn cv<T: Into<i64>>(a: T) -> i32 { Self::lo((a.into() % P6) as i32) }
		pub fn inv(self) -> Self { self.pow(P5-2) }
		pub fn pow<T: Into<i64>>(self, b: T) -> Self {
			let b = b.into(); if b == 0 { Self(1) } else {
				let mut res = self.pow(b/2); res *= res; if b % 2 == 1 {res *= self;} res
			}
		}
	}
	impl Add for Field { type Output = Self; fn add(self, a: Self) -> Self::Output { Self(Self::hi(self.0 + a.0)) }}
	impl Sub for Field { type Output = Self; fn sub(self, a: Self) -> Self::Output { Self(Self::lo(self.0 - a.0)) }}
	impl Mul for Field { type Output = Self; fn mul(self, a: Self) -> Self::Output { Self(Self::cv(self.0 as i64 * a.0 as i64)) }}
	impl Div for Field { type Output = Self; fn div(self, a: Self) -> Self::Output { self * a.inv() }}
	impl Neg for Field { type Output = Self; fn neg(self) -> Self::Output { Self(Self::lo(-self.0)) }}
	impl AddAssign for Field { fn add_assign(&mut self, a: Self) { *self = *self + a; } }
	impl SubAssign for Field { fn sub_assign(&mut self, a: Self) { *self = *self - a; } }
	impl MulAssign for Field { fn mul_assign(&mut self, a: Self) { *self = *self * a; } }
	impl DivAssign for Field { fn div_assign(&mut self, a: Self) { *self = *self / a; } }
	use std::fmt::{Display, Formatter, Result};
	impl Display for Field { fn fmt(&self, f: &mut Formatter) -> Result { write!(f, "{}", self.0) } }
}
#[allow(unused_imports)] use field::{Field, Field as Z, Z0, Z1};
//}}}
// Square Matrix (Field) {{{
type MatT = Field;
const MAT_T_0: MatT = Z0;
const MAT_T_1: MatT = Z1;
#[derive(Debug,Clone)] struct Mat { n: usize, a: Vec<MatT> }
#[allow(dead_code)] impl Mat {
	fn new(n:usize)->Self{Self{n,a:vec![MAT_T_0;n*n]}}
	fn diag(n:usize,v:MatT)->Self{let mut m=Self::new(n);let mut p=0;for _ in 0..n{m.a[p]=v;p+=n+1;}m}
	fn pow(&self,n:u64)->Self{if n==0{Self::diag(self.n,MAT_T_1)}else{let mut t=self.pow(n/2);t*=t.clone();if n%2==1{t*=self.clone();}t}}
	fn range(&self,r:Range<usize>,c:Range<usize>)->Vec<Vec<MatT>>{if r.start<r.end||c.start<c.end{Vec::new()}else{let mut res=vec![vec![MAT_T_0;c.end-c.start];r.end-r.start];
		for i in r.start..r.end{let ir=i-r.start;let ii=i*self.n+c.start;for j in 0..c.end-c.start{res[ir][j]=self.a[ii+j];}}res}}
	fn at(&self,r:usize,c:usize)->MatT{self.a[r*self.n+c]}
	fn at_mut<'a>(&'a mut self,r:usize,c:usize)->&'a mut MatT{&mut self.a[r*self.n+c]}//'
}
impl Mul for Mat{type Output=Self;fn mul(self,o:Self)->Self::Output{assert!(self.n==o.n);let n=self.n;let mut res=Self::new(n);
	for ii in(0..n).map(|i|i*n){for j in 0..n{let mut t=MAT_T_0;let mut kk=j;for k in 0..n{t+=self.a[ii+k]*o.a[kk];kk+=n;}res.a[ii+j]=t;}}res}}
impl Add for Mat{type Output=Self;fn add(mut self,o:Self)->Self{self+=o;self}}
impl Sub for Mat{type Output=Self;fn sub(mut self,o:Self)->Self{self-=o;self}}
impl MulAssign for Mat{fn mul_assign(&mut self,a:Self){*self=self.clone()*a;}}
impl AddAssign for Mat{fn add_assign(&mut self,o:Self){assert!(self.n==o.n);for(x,y)in self.a.iter_mut().zip(o.a.into_iter()){*x+=y;}} }
impl SubAssign for Mat{fn sub_assign(&mut self,o:Self){assert!(self.n==o.n);for(x,y)in self.a.iter_mut().zip(o.a.into_iter()){*x-=y;}} }
impl PartialEq for Mat{fn eq(&self,o:&Self)->bool{self.n==o.n&&self.a==o.a}}impl Eq for Mat{}
// }}}

fn main() {
	let mut rin = reader();
	let mut rout = writer();

	let n = rin.l();
	let m = rin.u();
	let mut mat = Mat::new(m);
	for i in 1..m {
		*mat.at_mut(i,i-1) = Z1;
	}
	*mat.at_mut(0,0) = Z1;
	*mat.at_mut(0,m-1) = Z1;
	let mat = mat.pow(n as u64);
	let sol = mat.at(0,0);
	writeln!(rout, "{}", sol).ok();
}


use std::io;
use std::io::BufRead;

fn main() {
    let stdin = io::stdin();
    let mut lines = stdin.lock().lines();

    let input_string = lines.next().unwrap().expect("input reading failed");
    let len = input_string.len();
    let iter = input_string.chars().take(len / 2 + 1);
    let mut reverse = input_string.chars().rev().take(len / 2 + 1);
    let mut palindrome = true;
    let mut same_char = true;

    // input string is non-empty
    let my_char = input_string.chars().nth(0).unwrap();

    for char_a in iter {
        if char_a != my_char {
            same_char = false;
        }

        let char_b = match reverse.next() {
            Some(c) => c,
            None => {
                break;
            }
        };

        if char_a != char_b {
            palindrome = false;
            break;
        }
    }

    let mut count = len;
    if palindrome {
        if same_char {
            count = 0;
        } else {
            count = len - 1;
        }
    }

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


use std::collections::HashSet;

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

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

    fn next_line(&self) -> String {
        let mut line = String::new();
        std::io::stdin().read_line(&mut line).expect("Fail to read");
        line
    }

    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop_front() {
                break token.parse::<T>().ok().unwrap();
            }
            let line = self.next_line();
            self.buffer = line.split_whitespace().map(String::from).collect();
        }
    }

    fn next_n<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.next::<T>()).collect()
    }
}

fn _main() {
    let mut scan = Scan::new();
    let line = scan.next_line();
    let tline = line.trim();
    let result = 26 + 25 * tline.len();
    println!("{}", result);
}

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


use std::str::{FromStr};

fn main() {
  let mut r = Read::new();
  let ln = r.many();
  print!("{}", solve(ln[0], ln[1], ln[2]));
}

fn solve(t: i32, l: i32, r: i32) -> i64 {
  let b = 1000000007;
  let mut f = vec![0;(r + 1) as usize];
  for i in 1..r as i64 + 1 {
    for j in 2..r as i64 / i + 1 {
      f[(i * j) as usize] = (f[i as usize] + i * j * (j - 1) / 2) % b;
    }
  }

  f[l as usize..r as usize + 1].iter().fold((0, 1), |(s, p), fi| ((s + p * fi) % b, p * t as i64 % b)).0
}

struct Read { s: String }

impl Read {
  fn new() -> Read {
    Read{s: String::new()}
  }

  #[allow(unused_must_use)]
  fn line(&mut self) -> &str {
    self.s.clear();
    std::io::stdin().read_line(&mut self.s);
    self.s.trim()
  }

  fn one<T: FromStr>(&mut self) -> T where <T as FromStr>::Err: std::fmt::Debug {
    self.line().parse().unwrap()
  }

  fn many<T: FromStr>(&mut self) -> Vec<T> where <T as FromStr>::Err: std::fmt::Debug {
    self.line().split(' ').map(|x| x.parse().unwrap()).collect()
  }
}


use std::collections::HashMap;
use std::io;
use std::str::FromStr;

fn get_num() -> usize {
    let mut input = String::new();

    io::stdin().read_line(&mut input).expect("");

    usize::from_str(input.trim()).unwrap()
}

fn main() {
    let mut m = HashMap::new();

    m.insert(0, "zero");
    m.insert(1, "one");
    m.insert(2, "two");
    m.insert(3, "three");
    m.insert(4, "four");
    m.insert(5, "five");
    m.insert(6, "six");
    m.insert(7, "seven");
    m.insert(8, "eight");
    m.insert(9, "nine");
    m.insert(10, "ten");
    m.insert(11, "eleven");
    m.insert(12, "twelve");
    m.insert(13, "thirteen");
    m.insert(14, "fourteen");
    m.insert(15, "fifteen");
    m.insert(16, "sixteen");
    m.insert(17, "seventeen");
    m.insert(18, "eighteen");
    m.insert(19, "nineteen");
    m.insert(20, "twenty");
    m.insert(30, "thirty");
    m.insert(40, "forty");
    m.insert(50, "fifty");
    m.insert(60, "sixty");
    m.insert(70, "seventy");
    m.insert(80, "eighty");
    m.insert(90, "ninety");

    let n = get_num();

    if n < 20 || m.contains_key(&n) {
        println!("{}", m.get(&n).unwrap());
    } else {
        println!(
            "{}-{}",
            m.get(&(n / 10 * 10)).unwrap(),
            m.get(&(n % 10)).unwrap()
        );
    }
}


use std::io;

fn read_line() -> String {
    let mut input_line = String::new();
    io::stdin().read_line(&mut input_line).unwrap();
    return String::from(input_line.trim());
}

fn read_line_vec() -> Vec<u32> {
    return read_line().split(' ')
        .map(|s| s.parse().unwrap())
        .collect();
}

fn resolve(n: u32) -> String {
    let s = match n {
        0 => "zero",
        10 => "ten",
        1 => "one",
        11 => "eleven",
        2 => "two",
        12 => "twelve",
        20 => "twenty",
        3 => "three",
        13 => "thirteen",
        30 => "thirty",
        4 => "four",
        14 => "fourteen",
        40 => "forty",
        5 => "five",
        15 => "fifteen",
        50 => "fifty",
        6 => "six",
        16 => "sixteen",
        60 => "sixty",
        7 => "seven",
        17 => "seventeen",
        70 => "seventy",
        8 => "eight",
        18 => "eighteen",
        80 => "eighty",
        9 => "nine",
        19 => "nineteen",
        90 => "ninety",
        _ => panic!("WHAAAAT")
    };
    return String::from(s);
}

fn main() {
    let n: u32 = read_line().parse().unwrap();
    if n <= 20 || n % 10 == 0 {
        let s = resolve(n);
        println!("{}", s);
    } else {
        let s2 = resolve(n % 10);

        let s1 = resolve(10 * (n / 10));
        println!("{}-{}", s1, s2);
    }
}


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

fn main() -> () {

    let mut buffer = String::new();
    let stdin = io::stdin();
    let mut handle = stdin.lock();

    handle.read_to_string(&mut buffer).expect("stdin");

    let mut arr : Vec<_> = buffer.split_whitespace().map(|x| x.parse::<i64>().unwrap() ).collect();

    let n = arr[0];
    let m = arr[1];

    let max_seats = arr.iter().skip(2).max().unwrap();
    let s = arr.iter().skip(2).sum::<i64>();
    let b = (s + m)/n + if (s+m) % n != 0 { 1 } else { 0 };

    use std::cmp;

    println!("{} {}", cmp::max( max_seats, &b ), max_seats + m );
}


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

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

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

// ここまで

fn run() {
    input! {
        n: usize,
        m: usize,
        a: [usize; n],
    }
    let max = *a.iter().max().unwrap() + m;
    let mut a = a;
    for _ in 0..m {
        let mut min = (1000000, 0);
        for (i, a) in a.iter().enumerate() {
            min = std::cmp::min(min, (*a, i));
        }
        a[min.1] += 1;
    }
    let min = *a.iter().max().unwrap();
    println!("{} {}", min, max);
}

fn main() {
    run();
}


use std::io;
use std::cmp::max;

fn main() {
  let stdin = io::stdin();
  let mut s = String::new();
  stdin.read_line(&mut s).unwrap();
  let a: Vec<i32> = s.split_whitespace()
    .map(|x| x.parse().unwrap())
    .collect();

  s = String::new();
  stdin.read_line(&mut s).unwrap();
  let v: Vec<i32> = s.split_whitespace()
    .map(|x| x.parse().unwrap())
    .collect();

  let mut cmax = 0;
  for i in 1..v.len() {
    cmax = max(cmax, v[i-1] - v[i]);
  }

  println!("{}", max(cmax - a[1], 0));
}


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

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

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

// ここまで

fn run() {
    input! {
        a: (u32, u32),
        b: (u32, u32),
        s: chars,
    }
    let mut f = 0;
    f += s[0].to_digit(10).unwrap() * 10 * 60;
    f += s[1].to_digit(10).unwrap() * 60;
    f += s[3].to_digit(10).unwrap() * 10;
    f += s[4].to_digit(10).unwrap();
    assert!((f - 300) % a.0 == 0);
    let start = f;
    let end = start + a.1;
    let mut p = 300;
    let mut ans = 0;
    while p < 24 * 60 {
        let (s, e) = (p, p + b.1);
        let (l, r) = (std::cmp::max(s, start), std::cmp::min(e, end));
        if l < r {
            ans += 1;
        }
        p += b.0;
    }
    println!("{}", ans);
}

fn main() {
    run();
}


use std::io;
fn main(){
    let mut s=String::new();
    io::stdin().read_line(&mut s).expect("Something is wrong");
    let n=&s[0..s.find(' ').unwrap()];
    let mut n:i64=n.trim().parse().unwrap();
    let k=&s[s.find(' ').unwrap()+1..s.len()];
    let mut k:i64=k.trim().parse().unwrap();
    let mut a:i64=n;
    let mut p:i64=0;
    while a%10==0{
        p+=1;
        a/=10;
    }
    if p>=k{println!("{}",n)}
    else{k=k-p;
    match a%10{
        1|3|7|9=>{for c in 0..k{n*=10}println!("{}",n)},
        5=>{while a%5==0{p+=1;a/=5;}if k>=p{for c in 0..p{n*=2}for c in 0..k-p{n*=10}}else{for c in 0..k{n*=2}}println!("{}",n);},
        _=>{while a%2==0{p+=1;a/=2;}if k>=p{for c in 0..p{n*=5}for c in 0..k-p{n*=10}}else{for c in 0..k{n*=5}}println!("{}",n);},
    }
}
}


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

// Be careful for n = 10^6. In Codeforces, usize is a 32-bit integer.
fn sieve(n: i64) -> (Vec<i64>, Vec<bool>) {
    let mut is_prime = vec![true; (n as usize) + 1];
    is_prime[0] = false;
    is_prime[1] = false;
    let mut primes = Vec::new();
    for i in 2..=n {
        if is_prime[i as usize] {
            primes.push(i);
            let mut j = i * i;
            while j <= n {
                is_prime[j as usize] = false;
                j += i;
            }
        }
    }
    (primes, is_prime)
}

fn lower_bound(arr: &[i64], target: i64) -> usize {
    let mut lo = 0;
    let mut hi = arr.len();
    while lo < hi {
        let mid = lo + (hi - lo) / 2;
        if arr[mid] >= target {
            hi = mid;
        } else {
            lo = mid + 1;
        }
    }
    lo
}

fn count_primes(primes: &[i64], lo: i64, hi: i64) -> i64 {
    // How many primes are there in [lo, hi]?
    let lb_1 = lower_bound(primes, lo) as i64;
    let lb_2 = lower_bound(primes, hi + 1) as i64;
    lb_2 - lb_1
}

fn pred(a: i64, b: i64, k: i64, l: i64, primes: &[i64], is_prime: &[bool]) -> bool {
    // For ALL x in [a, b - l + 1], are there at least k prime numbers in [x, x + l - 1]?

    // window: [a, a + l - 1]
    let mut prime_count = count_primes(primes, a, a + l - 1);
    if prime_count < k {
        return false;
    }
    for x in (a + 1)..=(b - l + 1) {
    // for i in 1..(b - l - a + 2) {
    //     let x = a + i;
        // window: [x, x + l - 1]
        // previous window: [x - 1, x + l - 2]
        // if x - 1 was prime, remove it
        if is_prime[(x - 1) as usize] {
            prime_count -= 1;
        }

        // if x + l - 1 is prime, add it
        if is_prime[(x + l - 1) as usize] {
            prime_count += 1;
        }

        if prime_count < k {
            return false;
        }
    }
    true
}

fn search_l(a: i64, b: i64, k: i64, primes: &[i64], is_prime: &[bool]) -> i64 {
    let mut lo = 1;
    let mut hi = b - a + 2;
    while lo < hi {
        let mid = lo + (hi - lo) / 2;
        if pred(a, b, k, mid, primes, is_prime) {
            hi = mid;
        } else {
            lo = mid + 1;
        }
    }
    if lo == b - a + 2 {
        -1
    } else {
        lo
    }
}

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

    let (primes, is_prime) = sieve(1000005);
    let ans = search_l(a, b, k, &primes, &is_prime);
    writeln!(out, "{}", ans).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);
}


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

fn count_bits(n: u64) -> u64 {
    let mut n = n;
    let mut ans = 0;
    while n > 0 {
        ans += 1;
        n >>= 1;
    }
    ans
}

fn solve<R: io::BufRead, W: io::Write>(scan: &mut Scanner<R>, out: &mut W) {
    let n: u64 = scan.token();
    let k: u64 = scan.token();
    // Maximize the xor-sum of at most k numbers from 1 to n
    // For any bit pattern that represents a positive number, its negation is always less than the number itself.
    // For example, n = 6 = 110 -> neg(n) = 001
    // n ^ neg(n) = 111
    // The answer is num_bits(n) ones, if k >= 2
    if k == 1 {
        writeln!(out, "{}", n).ok();
        return;
    }
    let num_bits = count_bits(n);
    let mut ans = 0u64;
    for i in 0..(num_bits) {
        ans = ans | (1 << i);
    }
    writeln!(out, "{}", ans).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);
}

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

    pub fn tokens<T: str::FromStr>(&mut self) -> Vec<T> {
        assert!(self.buffer.is_empty());
        let mut input = String::new();
        self.reader.read_line(&mut input).expect("Failed read");
        input
            .split_whitespace()
            .map(|x| x.parse().ok().expect("Failed parse"))
            .collect()
    }
}


// Try Codeforces
// author: Leonardone @ NEETSDKASU

fn main() {
    let mut stdin = String::new();
    std::io::Read::read_to_string(
        &mut std::io::stdin(),
        &mut stdin).unwrap();
    let mut stdin = stdin.split_whitespace();
    let mut get = || stdin.next().unwrap();
    macro_rules! get {
        () => (get().parse::<i64>().unwrap());
    }

    let n = get!();
    let k = get!();

    if k == 1 {
        println!("{}", n);
    } else {
        let mut t = n;
        let mut d = 0;
        while t > 0 {
            t >>= 1;
            d += 1;
        }
        let ans = (1i64 << d) - 1;
        println!("{}", ans);
    }

}


//spnauti-rusT {{{
use std::io::*; use std::str::{self,*}; use std::fmt::Debug;
#[allow(unused_imports)] use std::cmp::Ordering::{self,*};
#[allow(unused_imports)] use std::ops::{self,*};
#[allow(unused_imports)] use std::iter::{self,*};
#[allow(unused_imports)] use std::collections::*;
#[allow(unused_imports)] use std::cell::*;
#[allow(unused_macros)] macro_rules! min {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b < *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! max {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b > *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! l {
	($($v:ident),+ =$e:expr) => {$(let$v=$e;)+};
	($($v:ident),+:$t:ty=$e:expr) => {$(let$v:$t=$e;)+};
	(mut $($v:ident),+ =$e:expr) => {$(let mut$v=$e;)+};
	(mut $($v:ident),+:$t:ty=$e:expr) => {$(let mut$v:$t=$e;)+};
}
#[allow(unused_macros)] macro_rules! v {
	([$d:expr]$($s:tt)+) => {vec![v!($($s)+);$d]};
	([]) => {Vec::new()}; ([$e:expr]) => {Vec::with_capacity($e)}; (=$e:expr) => {$e};
}
#[allow(unused_macros)] macro_rules! rep { {[$c:expr]$($s:tt)+} => {for _ in 0..$c {$($s)+}} }
#[allow(dead_code)] fn reader() -> WordReaderC { WordReaderC::new() }
#[allow(dead_code)] fn writer() -> BufWriter<Stdout> { BufWriter::new(stdout()) }
struct WordReaderC {buf: Vec<u8>, pos: usize, q: std::io::StdinLock<'static>}//'
#[allow(dead_code)] impl WordReaderC {
	fn new() -> Self {
		let r = unsafe {&*Box::into_raw(Box::new(stdin()))};
		Self { q: r.lock(), buf: Vec::new(), pos: 0 }
	}
	fn next_line(&mut self) -> bool {
		self.buf.clear(); self.pos = 0;
		self.q.read_until(b'\n', &mut self.buf).unwrap_or(0) > 0
	}
	fn is_ws(c: u8) -> bool {
		c == b' ' || c == b'\r' || c == b'\n' || c == b'\t'
	}
	fn byte(&mut self) -> Option<u8> {
		if self.pos == self.buf.len() { if !self.next_line() { return None; } }
		self.pos += 1; Some(self.buf[self.pos - 1])
	}
	fn vb(&mut self) -> Vec<u8> {
		let mut s = Vec::with_capacity(8);
		let mut f = false;
		loop {
			if let Some(c) = self.byte() {
				if !Self::is_ws(c) {
					s.push(c);
					f = true;
				} else if f { break; }
			} else { break; }
		}
		s
	}
	fn s(&mut self) -> String { String::from_utf8(self.vb()).expect("invalid utf8") }
	fn i(&mut self) ->    i32 { self.p() }
	fn l(&mut self) ->    i64 { self.p() }
	fn u(&mut self) ->  usize { self.p() }
	fn f(&mut self) ->    f64 { self.p() }
	fn vi(&mut self, n: usize) -> Vec<i32> { self.vp(n) }
	fn vl(&mut self, n: usize) -> Vec<i64> { self.vp(n) }
	fn vu(&mut self, n: usize) -> Vec<usize> { self.vp(n) }
	fn ii(&mut self, n: usize) -> impl Iterator<Item=i32> { self.ip(n).into_iter() }
	fn iu(&mut self, n: usize) -> impl Iterator<Item=usize> { self.ip(n).into_iter() }
	fn p<T: FromStr>(&mut self) -> T where T::Err: Debug {
		let w = self.vb(); str::from_utf8(w.as_ref()).unwrap().parse::<T>().unwrap()
	}
	fn vp<T: FromStr>(&mut self, n: usize) -> Vec<T> where T::Err: Debug {
		(0..n).map(|_|self.p()).collect()
	}
	fn ip<T: FromStr>(&mut self, n: usize) -> impl Iterator<Item=T> where T::Err: Debug {
		self.vp(n).into_iter()
	}
}
//------------------- End rusT }}}

fn main() {
	let mut rin = reader();
	let mut rout = writer();

	let n = rin.u();
	l!(x,y = rin.l());
	let mut dp = v!([n+1]);
	dp.push(x);
	dp.push(x);
	for i in 2..=n {
		let z = dp[i-1] + x;
		let ii = i >> 1;
		dp.push(z);
		if i & 1 == 0 {
			min!(dp[i], dp[ii] + y);
		} else {
			min!(dp[i], dp[ii].min(dp[ii+1]) + y + x);
		}
	}
	writeln!(rout, "{}", dp[n]).ok();
}


#![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();
        handle.read_line(&mut buffer)
            .expect("scan_line_to_vec: failed at `handle.read_line`.");

        for s in chunks.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 (n, x, y) = scan_line!(usize u64 u64);

   let mut dp : Vec<u64> = Vec::with_capacity(n + 1);
   dp.resize(n + 1, 0);
   dp[0] = 0;
   dp[1] = x;

   for i in 2..(n+1) {
       let just_add = dp[i-1] + x;
       let just_double = dp[i/2] + y;
       let double_and_add = dp[(i-1)/2] + x + y;
       let double_and_delete = dp[(i+1)/2] + x + y;
       let mut best = min(just_add, min(double_and_add, double_and_delete));
       if i % 2 == 0 {
          best = min(best, just_double);
       }
       dp[i] = best;
   }

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


const INF: i64 = 1_000_000_000i64;

struct Graph {
    size: usize,
    edge: Vec<(usize, usize, i64, i64)>,
}

impl Graph {
    fn new(size: usize) -> Self {
        Graph {
            size: size,
            edge: vec![],
        }
    }
    fn add_edge(&mut self, src: usize, dst: usize, capa: i64, cost: i64) {
        assert!(src < self.size && dst < self.size && src != dst);
        self.edge.push((src, dst, capa, cost));
    }
    fn solve(&self, src: usize, dst: usize, flow: i64) -> Option<i64> {
        if src == dst {
            return Some(0);
        }
        let size = self.size;
        let edge = &self.edge;
        let mut deg = vec![0; size];
        for &(a, b, _, _) in edge.iter() {
            deg[a] += 1;
            deg[b] += 1;
        }
        let mut graph: Vec<_> = deg.into_iter().map(|d| Vec::with_capacity(d)).collect();
        for &(a, b, capa, cost) in edge.iter() {
            let x = graph[a].len();
            let y = graph[b].len();
            graph[a].push((b, capa, cost, y));
            graph[b].push((a, 0, -cost, x));
        }
        let mut ans = 0;
        let mut dp = Vec::with_capacity(size);
        let mut elem = Vec::with_capacity(size);
        let mut que = std::collections::VecDeque::new();
        for _ in 0..flow {
            dp.clear();
            dp.resize(size, (INF, src, 0));// コスト、親、親からの番号
            dp[src] = (0, src, 0);
            elem.clear();
            elem.resize(size, false);
            elem[src] = true;
            que.push_back(src);
            while let Some(v) = que.pop_front() {
                elem[v] = false;
                let (c, _, _) = dp[v];
                for (i, &(u, capa, cost, _)) in graph[v].iter().enumerate() {
                    if capa == 0 {
                        continue;
                    }
                    let c = c + cost;
                    if c < dp[u].0 {
                        dp[u] = (c, v, i);
                        if !elem[u] {
                            elem[u] = true;
                            que.push_back(u);
                        }
                    }
                }
            }
            if dp[dst].0 == INF {
                return None;
            }
            ans += dp[dst].0;
            let mut pos = dst;
            while pos != src {
                let (_, parent, k) = dp[pos];
                let inv = graph[parent][k].3;
                graph[parent][k].1 -= 1;
                graph[pos][inv].1 += 1;
                pos = parent;
            }
        }
        Some(ans)
    }
}

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

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

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

//

fn run() {
    input! {
        n: usize,
        m: usize,
        k: usize,
        c: i64,
        d: i64,
        a: [usize1; k],
        e: [(usize1, usize1); m],
    }
    let w = 101;
    let size = n * w + 2;
    let mut graph = Graph::new(size);
    let src = size - 1;
    let dst = src - 1;
    let pos = |a: usize, b: usize| -> usize {
        assert!(a < 101 && b < n);
        a * n + b
    };
    for a in a {
        graph.add_edge(src, pos(0, a), 1, 0);
    }
    for i in 0..w {
        graph.add_edge(pos(i, 0), dst, 50, c * i as i64);
    }
    for (a, b) in e {
        for i in 1..w {
            for j in 1..=k {
                let x = j as i64;
                graph.add_edge(pos(i - 1, a), pos(i, b), 1, d * (2 * x - 1));
                graph.add_edge(pos(i - 1, b), pos(i, a), 1, d * (2 * x - 1));
            }
        }
    }
    for i in 1..w {
        for j in 0..n {
            graph.add_edge(pos(i - 1, j), pos(i, j), 50, 0);
        }
    }
    let ans = graph.solve(src, dst, k as i64).unwrap();
    println!("{}", ans);
}

fn main() {
    run();
}


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 factorize(n: u64) -> Vec<(u64, u64)> {
    let mut n = n;
    let mut p = 2;
    let mut ans = Vec::new();
    while p * p <= n && n > 1 {
        let mut expo = 0;
        while n % p == 0 {
            expo += 1;
            n /= p;
        }
        if expo > 0 {
            ans.push((p, expo));
        }
        p += 1;
    }
    if n > 1{
        ans.push((n, 1));
    }
    ans
}

// fn is_power_of_two(n: u64) -> bool {
//     let expo = (n as f64).log2() as u32;
//     2u64.pow(expo) == n
// }

fn log2(n: u64) -> u64 {
    (n as f64).log2() as u64
}

fn find_min_ops(max_expo: u64, factors: &[(u64, u64)]) -> u64 {
    let m = max_expo.next_power_of_two();
    if m == max_expo {
        for (_, expo) in factors {
            if *expo < m {
                return 1 + log2(m);
            }
        }
        return log2(m);
    }
    1 + log2(m)
}

fn solve<R: io::BufRead, W: io::Write>(scan: &mut Scanner<R>, out: &mut W) {
    let n: u64 = scan.token();
    let factors = factorize(n);
    let mut min_n = 1;
    let mut max_expo = 1u64;
    for (p, expo) in &factors {
        min_n *= p;
        max_expo = max_expo.max(*expo);
    }
    if max_expo == 1 {
        writeln!(out, "{} 0", min_n).ok();
        return;
    }
    let min_ops = find_min_ops(max_expo, &factors);
    writeln!(out, "{} {}", min_n, min_ops).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);
}


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

macro_rules! parse_line_to_vec {
    ($t: ty) => {{
        let mut a_str = String::new();
        std::io::stdin().read_line(&mut a_str).expect("read error");
        (a_str
            .split_whitespace()
            .map(|x| x.parse::<$t>().unwrap())
            .collect::<Vec<$t>>())
    }};
}

fn solve() {
    let mut n = parse_line!(u64);
    if n == 1 {
        println!("1 0");
        return;
    }
    let mut max: u64 = 0;
    let mut min = std::u64::MAX;
    let mut val: u64 = 1;
    for i in 2..n {
        if i * i > n {
            break;
        }
        if n % i != 0 {
            continue;
        }
        val *= i;
        let mut cnt = 0;
        while n % i == 0 {
            n /= i;
            cnt += 1;
        }
        max = std::cmp::max(max, cnt);
        min = std::cmp::min(min, cnt);
    }
    if n != 1 {
        max = std::cmp::max(max, 1);
        min = std::cmp::min(min, 1);
        val *= n;
    }
    let mult = if max != min || max & (max - 1) != 0 {1} else {0};
    if max & (max - 1) != 0 {
        max <<= 1;
    }
    while max & (max - 1) != 0 {
        max &= max - 1;
    }
    println!("{} {}", val, mult + max.trailing_zeros());
}

fn main() {
    let tests = 1; // parse_line!(usize);
    for _ in 0..tests {
        solve();
    }
}


use std::io;

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

    let mut l: u64 = 1;
    let mut r: u64 = n;
    let mut m: u64;

    if tryv(n, 1) { println!("1"); return; }

    loop {
        // println!("l: {}, r: {}", l, r);
        if l + 1 == r {
            break;
        }
        m = (l + r) / 2;
        // println!("m: {}", m);
        if tryv(n, m) {
            r = m;
        } else {
            l = m;
        }
    }

    if tryv(n, l) {
        println!("{}", l);
    } else {
        println!("{}", r);
    }
    return;
}

fn tryv(nn: u64, k: u64) -> bool {
    // println!("n: {}, k: {}", nn, k);
    // println!("=====================");
    if k == 0 { return false; }
    let mut n = nn;
    let mut v: u64 = 0;
    loop {
        if v >= nn/2 + nn%2{
            return true;
        } else if v + n < nn/2 + nn%2 {
            return false;
        }

        if k >= n {
            v += n;
            n = 0;
        } else {
            v += k;
            n -= k;
        }

        n -= n/10;
        // println!("left: {}, vasya: {}", n, v);
    }
}


//! http://codeforces.com/contest/682/problem/A

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

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

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

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

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

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

fn main() {
  scanln!(n: u64, m: u64);
  let (nt, nb) = (n / 5, n % 5);
  let (mt, mb) = (m / 5, m % 5);
  let mut add_to_five = 0;
  for i in 1..6 {
    let nf = nt + if i <= nb { 1 } else { 0 };
    let mf = mt + if i != 5 && 5 - i <= mb { 1 } else { 0 };
    add_to_five += nf * mf;
  }
  println!("{}", add_to_five);
}


#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
#![allow(unused_mut)]
#![allow(unused_variables)]
#![allow(dead_code)]

#[allow(unused_macros)]
macro_rules! invec {
    ( $ t : ty ) => {{
        let mut s = String::new();
        match std::io::stdin().read_line(&mut s) {
            Ok(0) => Vec::<$t>::new(),
            Ok(n) => s
                .trim()
                .split_whitespace()
                .map(|s| s.parse::<$t>().unwrap())
                .collect::<Vec<$t>>(),
            Err(_) => Vec::<$t>::new(),
        }
    }};
}

#[allow(unused_macros)]
macro_rules! get {
      ($t:ty) => {
          {
              let mut line: String = String::new();
              std::io::stdin().read_line(&mut line).unwrap();
              line.trim().parse::<$t>().unwrap()
          }
      };
      ($($t:ty),*) => {
          {
              let mut line: String = String::new();
              std::io::stdin().read_line(&mut line).unwrap();
              let mut iter = line.split_whitespace();
              (
                  $(iter.next().unwrap().parse::<$t>().unwrap(),)*
              )
          }
      };
      ($t:ty; $n:expr) => {
          (0..$n).map(|_|
              get!($t)
          ).collect::<Vec<_>>()
      };
      ($($t:ty),*; $n:expr) => {
          (0..$n).map(|_|
              get!($($t),*)
          ).collect::<Vec<_>>()
      };
      ($t:ty ;;) => {
          {
              let mut line: String = String::new();
              std::io::stdin().read_line(&mut line).unwrap();
              line.split_whitespace()
                  .map(|t| t.parse::<$t>().unwrap())
                  .collect::<Vec<_>>()
          }
      };
      ($t:ty ;; $n:expr) => {
          (0..$n).map(|_| get!($t ;;)).collect::<Vec<_>>()
      };
}

#[allow(unused_macros)]
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let mut s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};

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

#[allow(unused_macros)]
macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };

    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };

    ($next:expr, [$t:tt]) => {
        {
            let len = read_value!($next, usize);
            (0..len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
        }
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };

    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };

    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

#[allow(unused_macros)]
#[cfg(debug_assertions)]
macro_rules! mydbg {
    //($arg:expr) => (dbg!($arg))
    //($arg:expr) => (println!("{:?}",$arg));
      ($($a:expr),*) => {
          eprintln!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);
      }
}
#[cfg(not(debug_assertions))]
macro_rules! mydbg {
    ($($arg:expr),*) => {};
}

macro_rules! echo {
    ($($a:expr),*) => {
          $(println!("{}",$a))*
      }
}

use std::cmp::*;
use std::collections::*;
use std::ops::{Add, Div, Mul, Sub};

#[allow(dead_code)]
static INF_I64: i64 = i64::max_value() / 2;
#[allow(dead_code)]
static INF_I32: i32 = i32::max_value() / 2;
#[allow(dead_code)]
static INF_USIZE: usize = usize::max_value() / 2;
#[allow(dead_code)]
static M_O_D: usize = 1000000007;
#[allow(dead_code)]
static PAI: f64 = 3.1415926535897932;

trait IteratorExt: Iterator {
    fn toVec(self) -> Vec<Self::Item>;
}

impl<T: Iterator> IteratorExt for T {
    fn toVec(self) -> Vec<Self::Item> {
        self.collect()
    }
}

trait CharExt {
    fn toNum(&self) -> usize;
    fn toAlphabetIndex(&self) -> usize;
    fn toNumIndex(&self) -> usize;
}
impl CharExt for char {
    fn toNum(&self) -> usize {
        return *self as usize;
    }
    fn toAlphabetIndex(&self) -> usize {
        return self.toNum() - 'a' as usize;
    }
    fn toNumIndex(&self) -> usize {
        return self.toNum() - '0' as usize;
    }
}

trait VectorExt {
    fn joinToString(&self, s: &str) -> String;
}
impl<T: ToString> VectorExt for Vec<T> {
    fn joinToString(&self, s: &str) -> String {
        return self
            .iter()
            .map(|x| x.to_string())
            .collect::<Vec<_>>()
            .join(s);
    }
}

trait StringExt {
    fn get_reverse(&self) -> String;
}
impl StringExt for String {
    fn get_reverse(&self) -> String {
        self.chars().rev().collect::<String>()
    }
}

trait UsizeExt {
    fn pow(&self, n: usize) -> usize;
}
impl UsizeExt for usize {
    fn pow(&self, n: usize) -> usize {
        return ((*self as u64).pow(n as u32)) as usize;
    }
}
macro_rules ! max { ( $ x : expr ) => ( $ x ) ; ( $ x : expr , $ ( $ xs : expr ) ,+ ) => { { use std :: cmp :: max ; max ( $ x , max ! ( $ ( $ xs ) ,+ ) ) } } ; }
macro_rules ! min { ( $ x : expr ) => ( $ x ) ; ( $ x : expr , $ ( $ xs : expr ) ,+ ) => { { use std :: cmp :: min ; min ( $ x , min ! ( $ ( $ xs ) ,+ ) ) } } ; }

fn main() {
    let n = get!(usize);
    let a = invec!(usize);
    let mut ans = 0;
    let mut p = 0;
    let mut dp = vec![vec![INF_USIZE; 3]; n + 5];
    dp[0][0] = 0;
    for i in 0..n {
        dp[i + 1][0] = min!(dp[i][0], dp[i][1], dp[i][2]) + 1;
        if a[i] == 1 {
            dp[i + 1][1] = min(dp[i][2], dp[i][0]);
        } else if a[i] == 2 {
            dp[i + 1][2] = min(dp[i][1], dp[i][0]);
        }
        if a[i] == 3 {
            dp[i + 1][1] = min(dp[i][0], dp[i][2]);
            dp[i + 1][2] = min(dp[i][0], dp[i][1]);
        }
    }
    ans = min!(dp[n][0], dp[n][1], dp[n][2]);
    echo!(ans);
}


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

use std::io::prelude::*;
use std::io::BufReader;
use std::cmp::{max, min};

fn get_line() -> String {
    let mut input = String::new();
    io::stdin().read_line(&mut input).unwrap();
    input
}

fn get_vec<T>() -> Vec<T>
where T: FromStr,
      <T as FromStr>::Err: std::fmt::Debug,
{
    get_line().split_whitespace().map(|k| k.parse().unwrap()).collect()
}

const N: i64 = 998_244_353;

fn extended_euclid(a: i64, b: i64) -> (i64, i64, i64) {
    if b == 0 {
        (a, 1, 0)
    } else {
        let (d0, x0, y0) = extended_euclid(b, a % b);
        (d0, y0, x0 - a / b * y0)
    }
}

fn main() {
    let (a, b, c) = {
        let input = get_line();
        let mut it = input.split_whitespace().map(|k| k.parse::<i64>().unwrap());
        (
            it.next().unwrap(),
            it.next().unwrap(),
            it.next().unwrap(),
            )
    };

    let mut s = [a, b, c];
    s.sort();
    let (a, b, c) = (s[0], s[1], s[2]);

    // Nombres d'arêtes possibles :
    // a * b + b * c + c * a
    // Nombre de combinaisons possibles :
    // 2^nap

    let modulo = |a, b| {
        if a % b < 0 {
            a % b + b
        } else {
            a % b
        }
    };

    let inv = |x| {
        modulo(extended_euclid(x, N).1, N)
    };

    let fact: Vec<i64> = (0..5001).scan(1, |state, x| {
        if x != 0 {
            *state = x * *state % N;
        }
        Some(*state)
    }).collect();

    let bc = |k, n| {
        fact[n as usize] * inv(fact[(n - k) as usize]) % N * inv(fact[k as usize]) % N
    };

    let np = |k, n| {
        fact[n as usize] * inv(fact[(n - k) as usize]) % N
    };

    let foo = |a, b| {
        (0..a + 1).map(|i| bc(i, a) * np(i, b) % N).fold(0, |acc, x| (acc + x) % N)
    };

    let ans = foo(a, b) * foo(a, c) % N * foo(b, c) % N;
    println!("{}", ans);
}


#[allow(unused_imports)]
use std::cmp::{max, min};
#[allow(unused_imports)]
use std::collections::{HashMap, HashSet};

mod util {
    use std::io::stdin;
    use std::str::FromStr;
    use std::fmt::Debug;

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

    #[allow(dead_code)]
    pub fn get<T: FromStr>() -> T
    where
        <T as FromStr>::Err: Debug,
    {
        let mut line: String = String::new();
        stdin().read_line(&mut line).unwrap();
        line.trim().parse().unwrap()
    }

    #[allow(dead_code)]
    pub fn gets<T: FromStr>() -> Vec<T>
    where
        <T as FromStr>::Err: Debug,
    {
        let mut line: String = String::new();
        stdin().read_line(&mut line).unwrap();
        line.split_whitespace()
            .map(|t| t.parse().unwrap())
            .collect()
    }

    #[allow(dead_code)]
    pub fn get2<T: FromStr, U: FromStr>() -> (T, U)
    where
        <T as FromStr>::Err: Debug,
        <U as FromStr>::Err: Debug,
    {
        let mut line: String = String::new();
        stdin().read_line(&mut line).unwrap();
        let mut iter = line.split_whitespace();
        (
            iter.next().unwrap().parse().unwrap(),
            iter.next().unwrap().parse().unwrap(),
        )
    }
}

fn gcd(a: usize, b: usize) -> usize {
    if b == 0 { a } else { gcd(b, a % b) }
}

fn lcm(a: usize, b: usize) -> usize {
    a * b / gcd(a, b)
}

// (gcd, x, y)
fn extgcd(a: i64, b: i64) -> (i64, i64, i64) {
    if b == 0 {
        (a, 1, 0)
    } else {
        let (gcd, x, y) = extgcd(b, a % b);
        (gcd, y, x - (a / b) * y)
    }
}

fn mod_pow(x: u64, n: u64, m: u64) -> u64 {
    let mut res = 1;
    let mut x = x;
    let mut n = n;
    while n > 0 {
        if n & 1 == 1 {
            res = (res * x) % m;
        }
        x = (x * x) % m;
        n = n >> 1;
    }
    res
}

fn mod_inverse(a: u64, m: u64) -> u64 {
    let (_, x, y) = extgcd(a as i64, m as i64);
    ((m as i64 + x) as u64 % m) % m
}

fn fact_table(len: usize, m: u64) -> Vec<u64> {
    let mut res = vec![1; len];
    for i in 1..len {
        res[i] = (i as u64 * res[i - 1]) % m;
    }
    res
}

// (a mod p, e when n! = a p^e)
fn mod_fact(n: u64, p: u64, fact: &Vec<u64>) -> (u64, u64) {
    if n == 0 {
        (1, 0)
    } else {
        let (a, b) = mod_fact(n / p, p, fact);
        let e = b + n / p;

        if n / p % 2 != 0 {
            (a * (p - fact[(n % p) as usize]) % p, e)
        } else {
            (a * fact[(n % p) as usize] % p, e)
        }
    }
}

fn mod_comb(n: u64, k: u64, p: u64, fact: &Vec<u64>) -> u64 {
    if n < k {
        0
    } else {
        let (a1, e1) = mod_fact(n, p, fact);
        let (a2, e2) = mod_fact(k, p, fact);
        let (a3, e3) = mod_fact(n - k, p, fact);

        if e1 > e2 + e3 {
            0
        } else {
            a1 * mod_inverse(a2 * a3 % p, p) % p
        }
    }
}

const M: u64 = 998244353;

fn between(a: u64, b: u64, fact: &Vec<u64>) -> u64 {
    let n = min(a, b);
    let m = max(a, b);

    (0..n + 1)
        .map(|k| {
            //let l = mod_comb(n, k, M, fact);
            //let r = (fact[m] * mod_inverse(fact[m - k], M)) % M;
            let l = mod_comb(n, k, M, fact) * mod_comb(m, k, M, fact) % M;
            let r = fact[k as usize];
            l * r % M
        })
        .fold(0, |x, y| (x + y) % M)
}

fn main() {
    let abc: Vec<u64> = util::gets();
    let fact = fact_table(100000, M);

    let mut ans = (between(abc[0], abc[1], &fact) * between(abc[1], abc[2], &fact)) % M;
    ans = (ans * between(abc[0], abc[2], &fact)) % M;

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


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 sieve(n: u32) -> (Vec<u32>, Vec<bool>) {
    let n = n as usize;
    let mut is_prime = vec![true; n + 1];
    let mut primes = Vec::new();
    for i in 2..n {
        if is_prime[i] {
            primes.push(i as u32);
            let mut j = i * i;
            while j <= n {
                is_prime[j] = false;
                j += i;
            }
        }
    }
    (primes, is_prime)
}

fn count_noldbach(n: u32, primes: &[u32], is_prime: &[bool]) -> u32 {
    let num_primes = primes.len();
    let mut count = 0;
    for i in 1..num_primes {
        let noldbach = primes[i - 1] + primes[i] + 1;
        if noldbach > n {
            break;
        }
        if is_prime[noldbach as usize] {
            count += 1;
        }
    }
    count
}

fn solve<R: io::BufRead, W: io::Write>(scan: &mut Scanner<R>, out: &mut W) {
    let (primes, is_prime) = sieve(1001);
    let n: u32 = scan.token();
    let k: u32 = scan.token();
    let ans = count_noldbach(n, &primes, &is_prime);
    if ans >= k {
        writeln!(out, "YES").ok();
    } else {
        writeln!(out, "NO").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);
}


// ---------- begin Matrix ----------
mod matrix {
    use std::ops::*;
    pub trait SemiRing: Add<Output = Self> + Mul<Output = Self> + Copy {
        fn zero() -> Self;
        fn one() -> Self;
    }
    #[derive(Clone)]
    pub struct SquareMatrix<R> {
        size: usize,
        buf: Box<[R]>,
    }
    #[allow(dead_code)]
    impl<R: SemiRing> SquareMatrix<R> {
        pub fn zero(size: usize) -> Self {
            SquareMatrix {
                size: size,
                buf: vec![R::zero(); size * size].into_boxed_slice(),
            }
        }
        pub fn identity(size: usize) -> Self {
            let mut e = Self::zero(size);
            for i in 0..size {
                e.buf[i * size + i] = R::one();
            }
            e
        }
        pub fn get(&self, x: usize, y: usize) -> &R {
            assert!(x < self.size && y < self.size);
            &self.buf[x * self.size + y]
        }
        pub fn get_mut(&mut self, x: usize, y: usize) -> &mut R {
            assert!(x < self.size && y < self.size);
            &mut self.buf[x * self.size + y]
        }
        pub fn matadd(&self, rhs: &Self) -> Self {
            assert!(self.size == rhs.size);
            let buf: Vec<R> = self
                .buf
                .iter()
                .zip(rhs.buf.iter())
                .map(|p| *p.0 + *p.1)
                .collect();
            SquareMatrix {
                size: self.size,
                buf: buf.into_boxed_slice(),
            }
        }
        pub fn matmul(&self, rhs: &Self) -> Self {
            let size = self.size;
            assert!(size == rhs.size);
            let mut res = Self::zero(size);
            for (x, a) in res.buf.chunks_mut(size).zip(self.buf.chunks(size)) {
                for (a, b) in a.iter().zip(rhs.buf.chunks(size)) {
                    for (x, b) in x.iter_mut().zip(b.iter()) {
                        *x = *x + *a * *b;
                    }
                }
            }
            res
        }
        pub fn mat_pow(&self, mut n: usize) -> Self {
            let size = self.size;
            let mut t = Self::identity(size);
            let mut s = self.clone();
            while n > 0 {
                if n & 1 == 1 {
                    t = t.matmul(&s);
                }
                s = s.matmul(&s);
                n >>= 1;
            }
            t
        }
    }
    #[allow(dead_code)]
    impl<R: SemiRing + Sub<Output = R>> SquareMatrix<R> {
        pub fn matsub(&self, rhs: &Self) -> Self {
            assert!(self.size == rhs.size);
            let buf: Vec<R> = self
                .buf
                .iter()
                .zip(rhs.buf.iter())
                .map(|p| *p.0 - *p.1)
                .collect();
            SquareMatrix {
                size: self.size,
                buf: buf.into_boxed_slice(),
            }
        }
    }
}
// ---------- end Matrix ----------
// ---------- begin ModInt ----------
mod modint {

    #[allow(dead_code)]
    pub struct Mod;
    impl Modulo for Mod {
        fn modulo() -> u32 {
            1_000_000_007
        }
        fn rem() -> u32 {
            2226617417
        }
        fn ini() -> u64 {
            582344008
        }
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    #[allow(dead_code)]
    impl<T: Modulo> ModInt<T> {
        fn reduce(x: u64) -> u32 {
            let b = (x as u32 * T::rem()) as u64;
            let t = x + b * T::modulo() as u64;
            let mut c = (t >> 32) as u32;
            if c >= T::modulo() {
                c -= T::modulo();
            }
            c as u32
        }
        fn new_unchecked(d: u32) -> Self {
            Self(d, PhantomData)
        }
        pub fn is_zero(&self) -> bool {
            self.0 == 0
        }
        pub fn new(d: u32) -> Self {
            Self::new_unchecked(Self::reduce(d as u64 * T::ini()))
        }
        pub fn zero() -> Self {
            Self::new(0)
        }
        pub fn one() -> Self {
            Self::new(1)
        }
        pub fn get(&self) -> u32 {
            Self::reduce(self.0 as u64)
        }
        /*
        pub fn pow(&self, mut n: u64) -> Self {
            let mut t = Self::one();
            let mut s = *self;
            while n > 0 {
                if n & 1 == 1 {
                    t *= s;
                }
                s *= s;
                n >>= 1;
            }
            t
        }
        pub fn inv(&self) -> Self {
            assert!(self.0 != 0);
            self.pow(T::modulo() as u64 - 2)
        }
        */
    }

    #[allow(dead_code)]
    pub fn mod_pow(r: u64, mut n: u64, m: u64) -> u64 {
        let mut t = 1 % m;
        let mut s = r % m;
        while n > 0 {
            if n & 1 == 1 {
                t = t * s % m;
            }
            s = s * s % m;
            n >>= 1;
        }
        t
    }
}
// ---------- end ModInt ----------
// ---------- begin input macro ----------
// reference: https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

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

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

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

use matrix::*;
type Mat = SquareMatrix<M>;

impl SemiRing for M {
    fn zero() -> Self {
        M::zero()
    }
    fn one() -> Self {
        M::one()
    }
}

fn run() {
    input! {
        w: [usize; 7],
    }
    // 0: 置いてok
    // 1: おいたらダメ
    let mut mat = vec![];
    for i in 1..=7 {
        let mut m = Mat::zero(1 << 7);
        for j in 0..(1 << i) {
            for k in 0..(1 << (2 * i - 1)) {
                if j & k > 0 {
                    continue;
                }
                let mut next = 0;
                for x in 0..i {
                    let left = x == 0 || (k >> (i + x - 1)) & 1 == 1;
                    let down = k >> x & 1 == 1;
                    let right = x == i - 1 || (k >> (i + x)) & 1 == 1;
                    if left && down && right {
                        next |= 1 << x;
                    }
                }
                *m.get_mut(next, j) += M::one();
            }
        }
        mat.push(m);
        let mut m = Mat::zero(1 << 7);
        for j in 0..(1 << i) {
            *m.get_mut(j, j) = M::one();
        }
        mat.push(m);
    }
    let mul = |m: &Mat, b: &[M]| -> Vec<M> {
        let mut res = vec![M::zero(); b.len()];
        for i in 0..b.len() {
            for j in 0..b.len() {
                res[i] += *m.get(i, j) * b[j];
            }
        }
        res
    };
    let mut b = vec![M::zero(); 1 << 7];
    let mut ini = false;
    let mut w = w;
    for (i, (w, mat)) in w.iter_mut().zip(mat.chunks(2)).enumerate().rev() {
        if !ini && *w > 0 {
            *w -= 1;
            ini = true;
            let i = i + 1;
            for k in 0..(1 << (i - 1)) {
                let mut bit = 0;
                for x in 0..i {
                    let left = x == 0 || k >> (x - 1) & 1 == 1;
                    let down = true;
                    let right = x == i - 1 || k >> x & 1 == 1;
                    if left && right && down {
                        bit |= 1 << x;
                    }
                }
                b[bit] += M::one();
            }
        }
        b = mul(&mat[1], &b);
        b = mul(&mat[0].mat_pow(*w), &b);
    }
    let ans = b[0].get();
    println!("{}", ans);
}

fn main() {
    run();
}


// ---------- begin ModInt ----------
// モンゴメリ乗算を用いる
// ほぼCodeforces用
// 素数のみ
mod modint {

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

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

    #[allow(dead_code)]
    pub enum Mod1_000_000_007 {}

    impl Modulo for Mod1_000_000_007 {
        fn modulo() -> u32 {
            1_000_000_007
        }
        fn rem() -> u32 {
            2226617417
        }
        fn ini() -> u64 {
            582344008
        }
    }

    #[allow(dead_code)]
    pub enum Mod998_244_353 {}

    impl Modulo for Mod998_244_353 {
        fn modulo() -> u32 {
            998_244_353
        }
        fn rem() -> u32 {
            998244351
        }
        fn ini() -> u64 {
            932051910
        }
    }

    #[allow(dead_code)]
    pub fn generate_umekomi_modulo(p: u32) {
        assert!(p < (1 << 31) && p > 2 && p & 1 == 1 && (2u32..).take_while(|v| v * v <= p).all(|k| p % k != 0));
        let mut t = 1u32;
        let mut s = !p + 1;
        let mut n = !0u32 >> 2;
        while n > 0 {
            if n & 1 == 1 {
                t *= s;
            }
            s *= s;
            n >>= 1;
        }
        let mut ini = (1u64 << 32) % p as u64;
        ini = (ini << 32) % p as u64;
        assert!(t * p == !0);
        println!("pub enum Mod{} {{}}", p);
        println!("impl Modulo for Mod_{} {{", p);
        println!("    fn modulo() -> u32 {{");
        println!("        {}", p);
        println!("    }}");
        println!("    fn rem() -> u32 {{");
        println!("        {}", t);
        println!("    }}");
        println!("    fn ini() -> u32 {{");
        println!("        {}", ini);
        println!("    }}");
    }

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

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

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

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

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

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

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

    impl<T: Modulo> Mul for ModInt<T> {
        type Output = ModInt<T>;
        fn mul(self, rhs: Self) -> Self::Output {
            Self::build(Self::reduce(self.0 as u64 * rhs.0 as u64))
        }
    }

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

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

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

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

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

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

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

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

    #[allow(dead_code)]
    impl<T: Modulo> ModInt<T> {
        fn reduce(x: u64) -> u32 {
            let b = (x as u32 * T::rem()) as u64;
            let t = x + b * T::modulo() as u64;
            let mut c = (t >> 32) as u32;
            if c >= T::modulo() {
                c -= T::modulo();
            }
            c as u32
        }
        pub fn new_unchecked(d: u32) -> Self {
            Self::build(Self::reduce(d as u64 * T::ini()))
        }
        pub fn new(d: u32) -> Self {
            Self::new_unchecked(d % T::modulo())
        }
        pub fn one() -> Self {
            Self::new_unchecked(1)
        }
        pub fn get(&self) -> u32 {
            Self::reduce(self.0 as u64)
        }
        pub fn pow(&self, mut n: u64) -> Self {
            let mut t = Self::one();
            let mut s = *self;
            while n > 0 {
                if n & 1 == 1 {
                    t *= s;
                }
                s *= s;
                n >>= 1;
            }
            t
        }
        pub fn inv(&self) -> Self {
            assert!(!self.is_zero());
            self.pow(T::modulo() as u64 - 2)
        }
    }
}
// ---------- end ModInt ----------
// ---------- begin Precalc ----------
mod precalc {
    use super::modint::*;
    #[allow(dead_code)]
    pub struct Precalc<T> {
        inv: Vec<ModInt<T>>,
        fact: Vec<ModInt<T>>,
        ifact: Vec<ModInt<T>>,
    }
    #[allow(dead_code)]
    impl<T: Modulo> Precalc<T> {
        pub fn new(n: usize) -> Precalc<T> {
            let mut inv = vec![ModInt::one(); n + 1];
            let mut fact = vec![ModInt::one(); n + 1];
            let mut ifact = vec![ModInt::one(); n + 1];
            for i in 2..(n + 1) {
                fact[i] = fact[i - 1] * ModInt::new_unchecked(i as u32);
            }
            ifact[n] = fact[n].inv();
            if n > 0 {
                inv[n] = ifact[n] * fact[n - 1];
            }
            for i in (1..n).rev() {
                ifact[i] = ifact[i + 1] * ModInt::new_unchecked((i + 1) as u32);
                inv[i] = ifact[i] * fact[i - 1];
            }
            Precalc {
                inv: inv,
                fact: fact,
                ifact: ifact,
            }
        }
        pub fn inv(&self, n: usize) -> ModInt<T> {
            assert!(n > 0);
            self.inv[n]
        }
        pub fn fact(&self, n: usize) -> ModInt<T> {
            self.fact[n]
        }
        pub fn ifact(&self, n: usize) -> ModInt<T> {
            self.ifact[n]
        }
        pub fn perm(&self, n: usize, k: usize) -> ModInt<T> {
            if k > n {
                return ModInt::zero();
            }
            self.fact[n] * self.ifact[n - k]
        }
        pub fn comb(&self, n: usize, k: usize) -> ModInt<T> {
            if k > n {
                return ModInt::zero();
            }
            self.fact[n] * self.ifact[k] * self.ifact[n - k]
        }
    }
}
// ---------- end Precalc ----------
// ---------- begin Matrix ----------
mod matrix {
    use std::ops::*;
    pub trait SemiRing: Add<Output = Self> + Mul<Output = Self> + Copy {
        fn zero() -> Self;
        fn one() -> Self;
    }
    #[derive(Clone)]
    pub struct SquareMatrix<R> {
        size: usize,
        buf: Box<[R]>,
    }
    #[allow(dead_code)]
    impl<R: SemiRing> SquareMatrix<R> {
        pub fn zero(size: usize) -> Self {
            SquareMatrix {
                size: size,
                buf: vec![R::zero(); size * size].into_boxed_slice(),
            }
        }
        pub fn identity(size: usize) -> Self {
            let mut e = Self::zero(size);
            for i in 0..size {
                e.buf[i * size + i] = R::one();
            }
            e
        }
        pub fn get(&self, x: usize, y: usize) -> &R {
            assert!(x < self.size && y < self.size);
            &self.buf[x * self.size + y]
        }
        pub fn get_mut(&mut self, x: usize, y: usize) -> &mut R {
            assert!(x < self.size && y < self.size);
            &mut self.buf[x * self.size + y]
        }
        pub fn matadd(&self, rhs: &Self) -> Self {
            assert!(self.size == rhs.size);
            let buf: Vec<R> = self
                .buf
                .iter()
                .zip(rhs.buf.iter())
                .map(|p| *p.0 + *p.1)
                .collect();
            SquareMatrix {
                size: self.size,
                buf: buf.into_boxed_slice(),
            }
        }
        pub fn matmul(&self, rhs: &Self) -> Self {
            let size = self.size;
            assert!(size == rhs.size);
            let mut res = Self::zero(size);
            for (x, a) in res.buf.chunks_mut(size).zip(self.buf.chunks(size)) {
                for (a, b) in a.iter().zip(rhs.buf.chunks(size)) {
                    for (x, b) in x.iter_mut().zip(b.iter()) {
                        *x = *x + *a * *b;
                    }
                }
            }
            res
        }
        pub fn mat_pow(&self, mut n: usize) -> Self {
            let size = self.size;
            let mut t = Self::identity(size);
            let mut s = self.clone();
            while n > 0 {
                if n & 1 == 1 {
                    t = t.matmul(&s);
                }
                s = s.matmul(&s);
                n >>= 1;
            }
            t
        }
    }
    #[allow(dead_code)]
    impl<R: SemiRing + Sub<Output = R>> SquareMatrix<R> {
        pub fn matsub(&self, rhs: &Self) -> Self {
            assert!(self.size == rhs.size);
            let buf: Vec<R> = self
                .buf
                .iter()
                .zip(rhs.buf.iter())
                .map(|p| *p.0 - *p.1)
                .collect();
            SquareMatrix {
                size: self.size,
                buf: buf.into_boxed_slice(),
            }
        }
    }
}
// ---------- end Matrix ----------
// ---------- begin input macro ----------
// reference: https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

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

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

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

use matrix::*;
type Mat = SquareMatrix<M>;

impl SemiRing for M {
    fn zero() -> Self {
        M::zero()
    }
    fn one() -> Self {
        M::one()
    }
}

fn run() {
    input! {
        w: [usize; 7],
    }
    // 0: 置いてok
    // 1: おいたらダメ
    let mut mat = vec![];
    for i in 1..=7 {
        let mut m = Mat::zero(1 << 7);
        for j in 0..(1 << i) {
            for k in 0..(1 << (2 * i - 1)) {
                if j & k > 0 {
                    continue;
                }
                let mut next = 0;
                for x in 0..i {
                    let left = x == 0 || (k >> (i + x - 1)) & 1 == 1;
                    let down = k >> x & 1 == 1;
                    let right = x == i - 1 || (k >> (i + x)) & 1 == 1;
                    if left && down && right {
                        next |= 1 << x;
                    }
                }
                *m.get_mut(next, j) += M::one();
            }
        }
        mat.push(m);
        let mut m = Mat::zero(1 << 7);
        for j in 0..(1 << i) {
            *m.get_mut(j, j) = M::one();
        }
        mat.push(m);
    }
    let mul = |m: &Mat, b: &[M]| -> Vec<M> {
        let mut res = vec![M::zero(); b.len()];
        for i in 0..b.len() {
            for j in 0..b.len() {
                res[i] += *m.get(i, j) * b[j];
            }
        }
        res
    };
    let mut b = vec![M::zero(); 1 << 7];
    let mut ini = false;
    let mut w = w;
    for (i, (w, mat)) in w.iter_mut().zip(mat.chunks(2)).enumerate().rev() {
        if !ini && *w > 0 {
            *w -= 1;
            ini = true;
            let i = i + 1;
            for k in 0..(1 << (i - 1)) {
                let mut bit = 0;
                for x in 0..i {
                    let left = x == 0 || k >> (x - 1) & 1 == 1;
                    let down = true;
                    let right = x == i - 1 || k >> x & 1 == 1;
                    if left && right && down {
                        bit |= 1 << x;
                    }
                }
                b[bit] += M::one();
            }
        }
        b = mul(&mat[1], &b);
        b = mul(&mat[0].mat_pow(*w), &b);
    }
    println!("{}", b[0]);
}

fn main() {
    run();
}