#include<algorithm>
#include<iomanip>
#include<iostream>
#include<map>
#include<set>
#include<stack>
#include<string>
#include<vector>
#include<bitset>
#include<cmath>
#define FOR(i,a,b) for(int i=(a); i<int(b); ++i)
#define RFOR(i,a,b) for(int i=(b)-1; i>=int(a); --i)
#define rep(i,n) FOR(i,0,n)
#define rep1(i,n) FOR(i,1,int(n)+1)
#define rrep(i, n) RFOR(i, 0, n)
#define rrep1(i, n) RFOR(i, 1, int(n) + 1)
#define all(c) begin(c), end(c)
#define al(d) d.begin(),d.end()
#define fill(n) std::setfill('0')<<std::right<<std::setw(n)
template <typename T>
using vec = std::vector<T>;
using vi = vec<int>;
using vvi = vec<vi>;
using pii = std::pair<int, int>;
using ll = long long;
using ld = long double;
using namespace std;
const int MOD = 1000000007;

template <typename T>
void putv(vector<T>& V){
	// cout << "The elements in the vector are: " << endl;
	for(auto x: V)
		cout << x << " ";
	cout << endl;
}
template <class T>
vector<T> getv(int n){
	vector<T> vec;
	rep(i,n){
		T input;
		cin >> input;
		vec.emplace_back(input);
	}
	return vec;
}

using AdjList = vector<vector<int>>;
using Weight = int;
using Flow = int;
struct Edge {
	int src, dst;
	Weight weight;
	Flow cap;
	Edge() : src(0), dst(0), weight(0) {}
	Edge(int s, int d, Weight w) : src(s), dst(d), weight(w) {}
};
using Edges = std::vector<Edge>;
using Graph = std::vector<Edges>;
using Array = std::vector<Weight>;
using Matrix = std::vector<Array>;
void add_edge(Graph &g, int a, int b, Weight w = 1) {
	g[a].emplace_back(a, b, w);
	g[b].emplace_back(b, a, w);
}
void add_arc(Graph &g, int a, int b, Weight w = 1) { g[a].emplace_back(a, b, w); }
// Recieve edge(=(int,int)) as an adj list.
AdjList getadj(int N, int M){
	// Initialize all lists of the graph as a empty vector.
	vector<int> init;
	vector<vector<int>> graph(N,init);
	rep(i,M){
		int a, b;
		cin >> a >> b;
		graph[a-1].emplace_back(b-1);
		graph[b-1].emplace_back(a-1);
	}
// rep(i,N)
// 	putv(graph[i]);
	return graph;
}

ll Manhattan_dist(ll x1, ll y1, ll x2, ll y2){
	return abs(x1-x2) + abs(y1-y2);
}
void out(bool ans){
	if(ans == true) cout << "yes" << endl;
	else cout << "no" << endl;
}
void Out(bool ans){
	if(ans == true) cout << "Yes" << endl;
	else cout << "No" << endl;
}
void OUT(bool ans){
	if(ans == true) cout << "YES" << endl;
	else cout << "NO" << endl;
}
ll gcd(const ll a, const ll b){
	return (b==0) ? a : gcd(b,a%b);
}
// $\min\{s\in\mathbb{N}:p^s|n\}$
ll hmt_p_divide_n(ll p, ll n){
	ll s = 0;
	while(n%p == 0){
		n /= p;
		s++;
	}
	return s;
}

#include<iostream>
using namespace std;
int main(){
	int D,G;
	cin >> D >> G;
	vi p,c;
	rep(i,D){
		int pv,cv;
		cin >> pv >> cv;
		p.emplace_back(pv);
		c.emplace_back(cv);
	}

	int ans = 1e9+7;
	for(int mask=0; mask<(1<<D); ++mask){

		int last0pos = -1; //まだ手をつけてないスコアの問題のうちの最高点数のもの
		int score = 0; // 1が立っている箇所の問題を全部解いた時の合計スコア
		int num_pr = 0; // 解いた問題数．最小値をansに更新していく

		rep(bit,D){ //各桁左から，
			if(mask>>bit & 1){ //１が立っていれば
				score += 100*(bit+1)*p[bit] + c[bit];
				num_pr += p[bit];
			}else last0pos = bit;
		}

		if(score >= G){
			ans = min(ans,num_pr);
		}else{ //まだ目標スコアに到達していなくても，１つずつ取って行って超えるかどうか．
			if(score < G){
				int needed_num = (G-score + (100*(last0pos+1))-1) / (100*(last0pos+1));
				if(p[last0pos] > needed_num)
					ans = min(ans, num_pr+needed_num);
			}
		}

	}
	cout << ans << endl;
}


Measured memory_bytes: 256