Problem:
Score : 300 points

Problem Statement

A programming competition site AtCode provides algorithmic problems.
Each problem is allocated a score based on its difficulty.
Currently, for each integer i between 1 and D (inclusive), there are p_i problems with a score of 100i points.
These p_1 + … + p_D problems are all of the problems available on AtCode.

A user of AtCode has a value called total score.
The total score of a user is the sum of the following two elements:

Base score: the sum of the scores of all problems solved by the user.

Perfect bonuses: when a user solves all problems with a score of 100i points, he/she earns the perfect bonus of c_i points, aside from the base score (1 ≤ i ≤ D).

Takahashi, who is the new user of AtCode, has not solved any problem.
His objective is to have a total score of G or more points.
At least how many problems does he need to solve for this objective?

Constraints

1 ≤ D ≤ 10

1 ≤ p_i ≤ 100

100 ≤ c_i ≤ 10^6

100 ≤ G

All values in input are integers.

c_i and G are all multiples of 100.

It is possible to have a total score of G or more points.

Input

Input is given from Standard Input in the following format:

D G
p_1 c_1
:
p_D c_D

Output

Print the minimum number of problems that needs to be solved in order to have a total score of G or more points. Note that this objective is always achievable (see Constraints).

Sample Input 1

2 700
3 500
5 800

Sample Output 1

3

In this case, there are three problems each with 100 points and five problems each with 200 points. The perfect bonus for solving all the 100-point problems is 500 points, and the perfect bonus for solving all the 200-point problems is 800 points. Takahashi's objective is to have a total score of 700 points or more.

One way to achieve this objective is to solve four 200-point problems and earn a base score of 800 points. However, if we solve three 100-point problems, we can earn the perfect bonus of 500 points in addition to the base score of 300 points, for a total score of 800 points, and we can achieve the objective with fewer problems.

Sample Input 2

2 2000
3 500
5 800

Sample Output 2

7

This case is similar to Sample Input 1, but the Takahashi's objective this time is 2000 points or more. In this case, we inevitably need to solve all five 200-point problems, and by solving two 100-point problems additionally we have the total score of 2000 points.

Sample Input 3

2 400
3 500
5 800

Sample Output 3

2

This case is again similar to Sample Input 1, but the Takahashi's objective this time is 400 points or more. In this case, we only need to solve two 200-point problems to achieve the objective.

Sample Input 4

5 25000
20 1000
40 1000
50 1000
30 1000
1 1000

Sample Output 4

66

There is only one 500-point problem, but the perfect bonus can be earned even in such a case.

Solution in Rust (1.15.1) (judge verdict: Accepted)

// ternary operation
#[allow(unused_macros)]
macro_rules! _if {
  ($_test:expr, $_then:expr, $_else:expr) => {
    if $_test { $_then } else { $_else }
  };
  ($_test:expr, $_pat:pat, $_then:expr, $_else:expr) => {
    match $_test {
      $_pat => $_then,
      _     => $_else
    }
  };
}

use std::io::{ stdin, stdout, BufWriter, Write, BufReader };
use my::WriteWithDelim;

#[derive(Debug)]
struct Quiz {
  num  : usize,
  point: usize,
  bonus: usize,
  total: usize,
}

fn abc104_c() {
  let stdin = stdin();
  let mut reader = my::ByteReader::with_capacity(16, BufReader::new(stdin.lock()));

  let stdout = stdout();
  let mut writer = BufWriter::new(stdout.lock());
  let mut i2b = my::Int2Byte::with_capacity(8);

  let d = reader.read_uint_until_sp::<usize>();
  let g = reader.read_uint_until_lf::<u64>();

  let mut vec = Vec::with_capacity(d);
  for i in 0..d {
    let point = (i + 1) * 100;
    let num   = reader.read_uint_until_sp::<usize>();
    let bonus = reader.read_uint_until_lf::<usize>();

    vec.push(Quiz {
      num  : num,
      point: point,
      bonus: bonus,
      total: num * point + bonus,
    });
  }

  let mut ans = <usize>::max_value();
  for i in 0..1 << d {
    let mut score = 0;
    let mut cnt   = 0;
    let mut max   = 0;

    for j in 0..d {
      if i & (1 << j) != 0 {
        score += vec[j].total as u64;
        cnt   += vec[j].num;
      } else {
        max = j;
      }
    }

    if score < g {
      let num = (g - score + vec[max].point as u64 - 1) / vec[max].point as u64;
      if num >= vec[max].num as u64 {
        continue;
      }
      cnt += num as usize;
    }
    ans = std::cmp::min(ans, cnt);
  }

  writer.write_lf(i2b.from_usize(ans));
  writer.flush().unwrap();
}

fn main() {
  abc104_c();
}

//------------------------------------------------------------------------
mod my {

  #[allow(dead_code)]
  pub fn rotate_right(vec: &mut Vec<u8>) {
    if vec.len() <= 1 {
      return;
    }

    let len = vec.len() - 1;
    let tmp = vec[len];
    for i in 0..len {
      vec[len - i] = vec[len - i - 1];
    }
    vec[0] = tmp;
  }

  #[allow(dead_code)]
  pub fn rotate_left(vec: &mut Vec<u8>) {
    if vec.len() <= 1 {
      return;
    }

    let len = vec.len() - 1;
    let tmp = vec[0];
    for i in 0..len {
      vec[i] = vec[i + 1];
    }
    vec[len] = tmp;
  }

  //----------------------------------------------------------------------
  const PLUS_SIGN : u8 = b'+';
  const MINUS_SIGN: u8 = b'-';
  const ASCII_0   : u8 = b'0';
  const ASCII_9   : u8 = b'9';

  const SP        : u8 = b' ';
  const LF        : u8 = b'\n';

  #[allow(dead_code)]
  pub fn is_ascii_digit(b: u8) -> bool {
    _if!(b >= ASCII_0 && b <= ASCII_9,
      true,
      false)
  }

  #[allow(dead_code)]
  pub fn is_ascii_uppercase(b: u8) -> bool {
    _if!(b >= b'A' && b <= b'Z',
      true,
      false)
  }

  #[allow(dead_code)]
  pub fn is_ascii_lowercase(b: u8) -> bool {
    _if!(b >= b'a' && b <= b'z',
      true,
      false)
  }

  #[allow(dead_code)]
  pub fn is_ascii_alphabetic(b: u8) -> bool {
    _if!(is_ascii_uppercase(b) || is_ascii_lowercase(b),
      true,
      false)
  }

  #[allow(dead_code)]
  pub fn to_ascii_lowercase(mut b: u8) -> u8 {
    if is_ascii_uppercase(b) {
      b += 0x20;
    }
    b
  }

  #[allow(dead_code)]
  pub fn to_ascii_uppercase(mut b: u8) -> u8 {
    if is_ascii_lowercase(b) {
      b -= 0x20;
    }
    b
  }

  //----------------------------------------------------------------------
  macro_rules! pub_fn_Int2Byte_from_ty {
    (uint, $($name:ident => $_type:ty),*) => {$(
      #[allow(dead_code)]
      pub fn $name(&mut self, mut i: $_type) -> &[u8] {
        self.buf.clear();
        if i == 0 {
          self.buf.push(ASCII_0);
          return self.buf.as_slice();
        }

        while i > 0 {
          self.buf.push((i % 10) as u8 + ASCII_0);
          i /= 10;
        }
        self.buf.reverse();
        self.buf.as_slice()
      }
    )*};

    (int, $($name:ident => $_type:ty),*) => {$(
      #[allow(dead_code)]
      pub fn $name(&mut self, mut i: $_type) -> &[u8] {
        self.buf.clear();
        if i == 0 {
          self.buf.push(ASCII_0);
          return self.buf.as_slice();
        }

        let mut negative = false;
        if i.is_negative() {
          negative = true;
          i = i.abs();
        }

        while i > 0 {
          self.buf.push((i % 10) as u8 + ASCII_0);
          i /= 10;
        }
        if negative {
          self.buf.push(MINUS_SIGN);
        }
        self.buf.reverse();
        self.buf.as_slice()
      }
    )*};
  }

  #[derive(Debug)]
  pub struct Int2Byte {
    buf: Vec<u8>,
  }

  impl Int2Byte {
    #[allow(dead_code)]
    pub fn new() -> Self {
      Int2Byte {
        buf: Vec::new(),
      }
    }

    #[allow(dead_code)]
    pub fn with_capacity(capa: usize) -> Self {
      Int2Byte {
        buf: Vec::with_capacity(capa),
      }
    }

    pub_fn_Int2Byte_from_ty!(
      uint,
      from_usize => usize,
      from_u8    => u8,
      from_u16   => u16,
      from_u32   => u32,
      from_u64   => u64
    );

    pub_fn_Int2Byte_from_ty!(
      int,
      from_isize => isize,
      from_i8    => i8,
      from_i16   => i16,
      from_i32   => i32,
      from_i64   => i64
    );
  } // impl Int2Byte

  //----------------------------------------------------------------------
  use std::io::{ BufRead, BufWriter, Write };
  use std::fmt::Debug;
  use std::ops::{ Add, Sub, Mul, Neg, Rem };
  use std::str::{ self, FromStr };
  use std::mem;

  //----------------------------------------------------------------------
  #[allow(dead_code)]
  pub fn intersection<T>(mut x: (T, T), mut y: (T, T)) -> Option<(T, T)>
    where T: PartialOrd +
             Copy +
             Debug
  {
    if x.0 > x.1 {
      mem::swap(&mut x.0, &mut x.1);
    }
    if y.0 > y.1 {
      mem::swap(&mut y.0, &mut y.1);
    }

    if x.0 >= y.1 || x.1 <= y.0 {
      return None;
    }

    if x.0 < y.0 {
      x.0 = y.0;
    }
    if x.1 > y.1 {
      x.1 = y.1;
    }

    Some(x)
  }

  #[allow(dead_code)]
  pub fn gcd<T>(x: T, y: T) -> T
    where T: Rem<Output=T> +
             Default +
             PartialEq +
             Copy +
             Debug
  {
    _if!(y == T::default(),
      x,
      gcd(y, x % y))
  }

  //----------------------------------------------------------------------
  pub trait WriteWithDelim {
    fn write_delim(&mut self, buf: &[u8], delim: &[u8]) -> usize;
    fn write_sp(&mut self, buf: &[u8]) -> usize;
    fn write_lf(&mut self, buf: &[u8]) -> usize;
  }

  impl<W> WriteWithDelim for BufWriter<W>
    where W: Write
  {
    #[allow(dead_code)]
    fn write_delim(&mut self, buf: &[u8], delim: &[u8]) -> usize
    {
      self.write(buf).unwrap() +
      self.write(delim).unwrap()
    }

    #[allow(dead_code)]
    fn write_sp(&mut self, buf: &[u8]) -> usize
    {
      self.write_delim(buf, b" ")
    }

    #[allow(dead_code)]
    fn write_lf(&mut self, buf: &[u8]) -> usize
    {
      self.write_delim(buf, b"\n")
    }
  } // impl<W> WriteWithDelim for BufWriter<W>

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

  #[allow(dead_code)]
  #[derive(Debug)]
  pub enum Direction {
    Horizontal,
    Vertical
  }

  #[derive(Debug)]
  pub struct ByteReader<R> {
    reader: R,
    buf   : Vec<u8>,
  }

  impl<R> ByteReader<R>
    where R: BufRead
  {
    #[allow(dead_code)]
    pub fn new(reader: R) -> Self {
      ByteReader {
        reader: reader,
        buf   : Vec::new(),
      }
    }

    #[allow(dead_code)]
    pub fn with_capacity(capa: usize, reader: R) -> Self {
      ByteReader {
        reader: reader,
        buf   : Vec::with_capacity(capa),
      }
    }

    //--------------------------------------------------------------------
    #[allow(dead_code)]
    pub fn read_1byte(&mut self) -> Option<u8> {
      self.buf.resize(1, 0);
      _if!(self.reader.read(&mut self.buf).unwrap() != 0,
        Some(self.buf[0]),
        None)
    }

    //--------------------------------------------------------------------
    fn read_until(&mut self, delim: u8) -> usize {
      self.buf.clear();
      self.reader.read_until(delim, &mut self.buf).unwrap()
    }

    #[allow(dead_code)]
    pub fn read_until_lf(&mut self) -> &[u8] {
      self.read_until(LF);
      self.buf.as_slice()
    }

    #[allow(dead_code)]
    pub fn read_until_sp(&mut self) -> &[u8] {
      self.read_until(SP);
      self.buf.as_slice()
    }

    //--------------------------------------------------------------------
    #[allow(dead_code)]
    pub fn read_byte_until_lf(&mut self) -> Vec<u8> {
      self.read_until(LF);
      let len = self.buf.len() - 1;
      if self.buf[len] == LF {
        self.buf.truncate(len);
      }
      self.buf.clone()
    }

    #[allow(dead_code)]
    pub fn read_string_until_lf(&mut self) -> String {
      unsafe { String::from_utf8_unchecked(self.read_byte_until_lf()) }
    }

    //--------------------------------------------------------------------
    fn parse_int<T>(&self) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Neg<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      let len = self.buf.len();
      let mut i = 0;
      let mut n = T::default();
      let mut minus = false;

      if self.buf[i] == MINUS_SIGN {
        minus = true;
        i += 1;
      } else if self.buf[i] == PLUS_SIGN {
        i += 1;
      }

      while i < len && is_ascii_digit(self.buf[i]) {
        n = (n * T::from(10)) + T::from(self.buf[i] - ASCII_0);
        i += 1;
      }

      _if!(minus,
        n.neg(),
        n)
    }

    fn parse_uint<T>(&self) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      let len = self.buf.len();
      let mut i = 0;
      let mut n = T::default();

      if self.buf[i] == PLUS_SIGN {
        i += 1;
      }

      while i < len && is_ascii_digit(self.buf[i]) {
        n = (n * T::from(10)) + T::from(self.buf[i] - ASCII_0);
        i += 1;
      }
      n
    }

    //--------------------------------------------------------------------
    #[allow(dead_code)]
    pub fn read_int_until_delim<T>(&mut self, delim: u8) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Neg<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      self.read_until(delim);
      self.parse_int()
    }

    // s -> n
    #[allow(dead_code)]
    pub fn read_int_until_lf<T>(&mut self) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Neg<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      self.read_int_until_delim(LF)
    }

    // s -> n
    #[allow(dead_code)]
    pub fn read_int_until_sp<T>(&mut self) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Neg<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      self.read_int_until_delim(SP)
    }

    //--------------------------------------------------------------------
    #[allow(dead_code)]
    pub fn read_uint_until_delim<T>(&mut self, delim: u8) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      self.read_until(delim);
      self.parse_uint()
    }

    // s -> n
    #[allow(dead_code)]
    pub fn read_uint_until_lf<T>(&mut self) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      self.read_uint_until_delim(LF)
    }

    // s -> n
    #[allow(dead_code)]
    pub fn read_uint_until_sp<T>(&mut self) -> T
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      self.read_uint_until_delim(SP)
    }

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

    fn from_utf8_unchecked(&mut self) -> &str {
      unsafe { str::from_utf8_unchecked(&self.buf) }
    }

    fn parse_tok<T>(&mut self) -> T
      where T: FromStr + Debug,
            <T as FromStr>::Err: Debug
    {
      self.from_utf8_unchecked()
        .trim()
        .parse()
        .unwrap()
    }

    // s -> n
    #[allow(dead_code)]
    pub fn parse_until_delim<T>(&mut self, delim: u8) -> T
      where T: FromStr + Debug,
            <T as FromStr>::Err: Debug
    {
      self.read_until(delim);
      self.parse_tok()
    }

    // s -> n
    #[allow(dead_code)]
    pub fn parse_until_lf<T>(&mut self) -> T
      where T: FromStr + Debug,
            <T as FromStr>::Err: Debug
    {
      self.parse_until_delim(LF)
    }

    // s -> n
    #[allow(dead_code)]
    pub fn parse_until_sp<T>(&mut self) -> T
      where T: FromStr + Debug,
            <T as FromStr>::Err: Debug
    {
      self.parse_until_delim(SP)
    }

    //--------------------------------------------------------------------
    #[allow(dead_code)]
    pub fn read_int_vec<T>(&mut self, n: usize, dir: Direction) -> Vec<T>
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Neg<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      let delim = _if!(dir, Direction::Horizontal, SP, LF);
      let mut vec = Vec::with_capacity(n);
      for _ in 0..n - 1 {
        vec.push(self.read_int_until_delim(delim));
      }
      vec.push(self.read_int_until_delim(LF));
      vec
    }

    #[allow(dead_code)]
    pub fn read_uint_vec<T>(&mut self, n: usize, dir: Direction) -> Vec<T>
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      let delim = _if!(dir, Direction::Horizontal, SP, LF);
      let mut vec = Vec::with_capacity(n);
      for _ in 0..n - 1 {
        vec.push(self.read_uint_until_delim(delim));
      }
      vec.push(self.read_uint_until_delim(LF));
      vec
    }

    // horizontal
    //
    // N
    // s1 s2 s3, ..., sN -> [n1, n2, n3, ..., nN]
    #[allow(dead_code)]
    pub fn read_int_vec_h<T>(&mut self) -> Vec<T>
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Neg<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      let n: usize = self.read_uint_until_lf();
      self.read_int_vec(n, Direction::Horizontal)
    }

    // horizontal
    //
    // N
    // s1 s2 s3, ..., sN -> [n1, n2, n3, ..., nN]
    #[allow(dead_code)]
    pub fn read_uint_vec_h<T>(&mut self) -> Vec<T>
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      let n: usize = self.read_uint_until_lf();
      self.read_uint_vec(n, Direction::Horizontal)
    }

    #[allow(dead_code)]
    pub fn read_uint_vec2<T>(&mut self, n: usize, m: usize) -> Vec<Vec<T>>
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      let mut vec = Vec::with_capacity(n);
      for _ in 0..n {
        vec.push(self.read_uint_vec(m, Direction::Horizontal));
      }
      vec
    }

    // N M
    // s11 s12 s13 ... s1M
    // s21 s22 s23 ... s2M
    // s31 s32 s33 ... s3M
    //   :
    // sN1 sN2 sN3 ... sNM
    // -> [
    //      [n11, n12, n13, ..., n1M],
    //      [n21, n22, n23, ..., n2M],
    //      [n31, n32, n33, ..., n3M],
    //          :
    //      [nN1, nN2, nN3, ..., nNM],
    //    ]
    #[allow(dead_code)]
    pub fn read_int_vec2<T>(&mut self, n: usize, m: usize) -> Vec<Vec<T>>
      where T: Add<Output=T> +
               Sub<Output=T> +
               Mul<Output=T> +
               Neg<Output=T> +
               Default +
               From<u8> +
               Debug
    {
      let mut vec = Vec::with_capacity(n);
      for _ in 0..n {
        vec.push(self.read_int_vec(m, Direction::Horizontal));
      }
      vec
    }

  } // impl<R> ByteReader<R>

} // mod my