CodeEff/ECCO huggingface dataset:
# Original solution
import re

d,g = list(map(int,input().split() ))
l = [list(map(int,input().split() ))+[100*(x+1)] for x in range(d) ] 

mondai_num = []

for k in range(2**d):

  #先に全完するカテゴリ(何百点問題を全完するか)を決め、回す
  bin_str = format(k, "0{}b".format(d) )#二進数の文字列を取得
  #これが全完する問題のリスト
  zenkan_list = [ x.start() for x in re.finditer("1",bin_str)  ] 
  

  #0~9のリストと和の初期化
  d_list = [i for i in range(d)]
  wa = 0
  cnt = 0
  #全完した点数のみ先に足す
  for i in zenkan_list:
    wa = wa+(l[i][0])*((i+1)*100)
    wa = wa + l[i][1]  
    cnt = cnt + l[i][0]
  #全完したやつだけで目標を超えたらそこでストップ
  if wa>=g:
    mondai_num.append( cnt )

  #全完したやつだけでたらなかったら素点が大きいやつを全完一歩手前まで足す
  else:
    #全完したカテゴリを除外
    for i in zenkan_list:
      d_list.remove(i)
    #残ったカテゴリの中で最大の点数のカテゴリを探す
    max_set = l[max(d_list)]

    for i in range( max_set[0]  ):
      wa = wa + max_set[2]
      if wa >= g:
        mondai_num.append(cnt + i+1 )
        break
print((min(mondai_num)))

# Optimized solution
import math
D,G = list(map(int,input().split()))
p = []
c = []
for i in range(D):
  P,C = list(map(int,input().split()))
  p.append(P)
  c.append(C)

res = float("inf")        
for i in range(2**D):
  bs = format(i,"0{}b".format(D))
  ans = 0
  cnt = 0
  #コンプするやつをたす
  for j in range(D):
    if bs[j] == "1":
      ans += (j+1)*100*p[j] + c[j]
      cnt += p[j]
  if ans >= G:
    res = min(cnt,res)
    continue

  #コンプしないやつを寸止めでたす
  for j in range(D-1,-1,-1):
    if bs[j] == "0":
      ans += (j+1)*100*(p[j]-1)
      cnt += (p[j]-1)
      if ans >= G:
        cnt -= (ans-G)//((j+1)*100)
        res = min(res,cnt)
        break
print(res)
# Original solution
d,g = list(map(int, input().split()))
p = []
c = []
for i in range(d):
    a,b = list(map(int, input().split()))
    p.append(a)
    c.append(b)
    
dp = [0 for i in range(sum(p) + 2)] 
for i in range(1,d+1):
    count_max = p[i-1]
    bonus = c[i-1]
    for j in range(sum(p)+1,0,-1):
        for k in range(1,count_max+1):
            if k < count_max:
                cc = 100 * i * k
            if k == count_max:
                cc = 100 * i * k + bonus
                
            if j - k >= 0:
                dp[j] = max(dp[j],dp[j-k] + cc)
                
for i,j in enumerate(dp):
    if g <= j:
        print(i)
        break

# Optimized solution
d,g = list(map(int, input().split()))
P = []
C = []
PC = []
for i in range(d):
    p,c = list(map(int, input().split()))
    P.append(p)
    C.append(c)
    PC.append((p,c))
    
P_sum = sum(P)
dp = [0 for i in range(P_sum + 1)]
for i,j in enumerate(PC):
    for k in range(P_sum,  -1, -1):
        for l in range(1,j[0]+1):
            if l + k <= P_sum:
                if l == j[0]:
                    cc = 100 * (i + 1)* l + j[1]
                else:
                    cc = 100 * (i + 1) * l
                dp[l + k] = max(dp[l + k ], dp[k] + cc)
                
for i,j in enumerate(dp):
    if j >= g:
        print(i)
        break
# Original solution
from operator import itemgetter

D, G = list(map(int, input().split()))
PC = [list(map(int, input().split())) for _ in range(D)]

def score(d, n, s, ans):
    if s >= G:
        ans = min(ans, n)
        return ans
    if d == D:
        if s >= G:
            ans = min(ans, n)
        return ans
    p, c = PC[d]
    for k in range(p+1):
        if k == p:
            ans = score(d+1, n+k, 100*(d+1)*k + c + s, ans)
        else:
            ans = score(d+1, n+k, 100*(d+1)*k + s, ans)
    return ans

print((score(0, 0, 0, 1000)))

# Optimized solution
from operator import itemgetter

D, G = list(map(int, input().split()))
PC = [list(map(int, input().split())) for _ in range(D)]

def com(d, s, ans):
    if d == D:
        ans.append(s)
        return ans
    a = s[:]
    a.append(1)
    ans = com(d+1, a, ans)
    b = s[:]
    b.append(0)
    ans = com(d+1, b, ans)
    return ans

L = com(0, [], [])
ans = 10000
for l in L:
    point = 0
    probs = 0
    uncom = []
    for i, com in enumerate(l):
        if com == 0:
            uncom.append(i)
        else:
            p, c = PC[i]
            point += (i+1)*100*p + c
            probs += p
    #print(probs, l)
    if point >= G:
        ans = min(ans, probs)
        continue
    uncom.sort(reverse=True)
    re = G - point
    for un in uncom:
        p, c = PC[un]
        #print(re, probs, p)
        if (un+1)*100*(p-1) >= re:
            rem = 1 if re % ((un+1)*100) > 0 else 0
            probs += re // ((un+1)*100) + rem
            re = 0
            break
        re -= (un+1)*100*(p-1)
        probs += p-1
    #print(probs)
    if re > 0:
        continue
    ans = min(ans, probs)
print(ans)
# Original solution
d, g = [int(i) for i in input().split()]

score = 0
p = []
c = []
for i in range(d):
    p_tmp, c_tmp = [int(i) for i in input().split()]
    p.append(p_tmp)
    c.append(c_tmp)

num = []
for i in range(2**d):
    num_tmp = 0
    score = 0
    not_comp = []
    for j in range(d):
        if i >> j & 1:
            score += p[j] * 100 * (j+1) + c[j]
            num_tmp += p[j]
        else:
            not_comp.append(j)

    for j in not_comp[::-1]:
        for k in range(p[j]-1):
            if score < g:
                score += 100 * (j+1)
                num_tmp += 1
            else:
                break
        else:
            continue
        break
    if score >= g:
        num.append(num_tmp)

ans = min(num)
print(ans)


# Optimized solution
d, g = [int(i) for i in input().split()]

score = 0
p = []
c = []
for i in range(d):
    p_tmp, c_tmp = [int(i) for i in input().split()]
    p.append(p_tmp)
    c.append(c_tmp)

num = []
for i in range(2**d):
    num_tmp = 0
    score = 0
    not_comp = []
    for j in range(d):
        if i >> j & 1:
            score += p[j] * 100 * (j+1) + c[j]
            num_tmp += p[j]
        else:
            not_comp.append(j)

    for j in not_comp[::-1]:
        if score < g:
            num_j = min(p[j]-1, (g-score-1)//(100*(j+1))+1)
            score += num_j * 100*(j+1)
            num_tmp += num_j
    if score >= g:
        num.append(num_tmp)

ans = min(num)
print(ans)
# Original solution

D, G = list(map(int, input().split()))
P = []

for i in range(D):
  p, c = list(map(int, input().split()))
  P.append((p, c))

ans = float("inf")

for i in range(2 ** D):
  score = 0
  index = []
  attempt = 0

  for j in range(D):
    if ((i >> j) & 1):
      p, c = list(map(int, P[j]))
      score += (c + p * (100 * (j+1) ))
      attempt += p
      index.append(j)

  if score >= G: # コンプリートボーナスのみでスコアを超えている場合
    ans = min(ans, attempt)
    continue

  for i in range(D)[::-1]: # 個別に計算して足していく
    if score >= G: # スコアを達成した場合は終了
      break

    if i in index: # コンプリートしてたりするやつはスキップ
      continue

    p, c = list(map(int, P[i]))
    for j in range(p):
      score += 100 * (i+1)
      attempt += 1
      if score >= G: # スコアを達成した場合は終了
        ans = min(ans, attempt)
        break
    else:
      index.append(i)

print(ans)


# Optimized solution


D, G = list(map(int, input().split()))
from itertools import chain

S = []
for i in range(D):
  p, c = list(map(int, input().split()))
  S.append((p, c))

L = []
for i in range(2**D):
  T = []
  for j in range(D):
    if (i>>j) & 1:
      T.append(j)
  L.append(T)

X = []
for l in L:
  score, count = 0, 0
  for m in l:
    p, c = S[m]
    score += c + (m+1) * 100 * p
    count += p
  else:
    X.append((score,count,l))

ans = float("inf")
for l in X:
  score, count, indexes = l

  if score >= G:
    ans = min(ans, count)
    continue
  
  end = False
  for i in list(range(D))[::-1]:
    if i in indexes:
      continue

    if end:
      break
    
    p, c = S[i]
    for _ in range(p):
      count += 1
      score += (i+1) * 100
      if score >= G:
        ans = min(ans, count)
        end = True
        break

print(ans)
# Original solution
import sys,math,collections,itertools,copy
input = sys.stdin.readline

D,G=list(map(int,input().split()))
score = []
maxScore = []
cos_per = []
for d in range(D):
    p,c=list(map(int,input().split()))
    tmp = [(d+1)*100]*p
    tmp[-1]+=c
    score.append(tmp)
    maxScore.append(sum(tmp))
    #cos_per.append([d+1,sum(tmp)/p])
    cos_per.append([d+1,d+1])
#-最大いくつの問題セットを必要とするか-#
maxScore.sort()
tmp = 0
for idx,mS in enumerate(maxScore):
    tmp += mS
    if tmp >= G:
        max_num = idx+1
        break
#-最小でいくつの問題セットを必要とするか-#
tmp = 0
j=0
for i in range(len(maxScore)-1,-1,-1):
    j+=1
    tmp += maxScore[i]
    if tmp >= G:
        min_num = j
        break
#-最小-2個はスコアが高いものを入れてよし-#
#cos_per.sort(key = lambda x:-x[1])
choice = set(range(1,D+1))
#choiceList = []
#for i in range(0,min_num-3):
 #   choiceList+=score[cos_per[i][0]-1]
 #   choice.discard(cos_per[i][0])
 #   max_num -=1
 
#-足し上げる-#

ans = float('inf')
for ch in itertools.permutations(choice,max_num):
    times = 0
    total = 0
    flag = 0
    for ci in ch:
        for sc in score[ci-1]:
            total += sc
            times += 1
            if total >= G:
                ans = min(ans,times)
                falg = 1
                break
    if flag ==1:
        break
print(ans)     


# Optimized solution
import sys,math,collections,itertools,copy
input = sys.stdin.readline

D,G=list(map(int,input().split()))
score = []
maxScore = []
cos_per = []
maxS = []
for d in range(D):
    p,c=list(map(int,input().split()))
    tmp = [(d+1)*100]*p
    tmp[-1]+=c
    score.append(tmp)
    maxScore.append(sum(tmp))
    maxS.append([p,sum(tmp)])
    #cos_per.append([d+1,sum(tmp)/p])
    cos_per.append([d+1,d+1])
#-最大いくつの問題セットを必要とするか-#
maxScore.sort()
tmp = 0
for idx,mS in enumerate(maxScore):
    tmp += mS
    if tmp >= G:
        max_num = idx+1
        break
#-最小でいくつの問題セットを必要とするか-#
tmp = 0
j=0
for i in range(len(maxScore)-1,-1,-1):
    j+=1
    tmp += maxScore[i]
    if tmp >= G:
        min_num = j
        break
#-最小-2個はスコアが高いものを入れてよし-#
#cos_per.sort(key = lambda x:-x[1])
choice = set(range(1,D+1))
#choiceList = []
#for i in range(0,min_num-3):
 #   choiceList+=score[cos_per[i][0]-1]
 #   choice.discard(cos_per[i][0])
 #   max_num -=1
 
#-足し上げる-#

ans = float('inf')
for ch in itertools.permutations(choice,max_num):
    times = 0
    total = 0
    flag = 0
    for ci in ch:
        if total + maxS[ci-1][1] <G:
            total += maxS[ci-1][1]
            times += maxS[ci-1][0]
        else:
            for sc in score[ci-1]:
                total += sc
                times += 1
                if total >= G:
                    ans = min(ans,times)
                    falg = 1
                    break
    if flag ==1:
        break
print(ans)
# Original solution
D, G = list(map(int, input().split()))
p = [0 for i in range(D)]
c = [0 for i in range(D)]
for i in range(D):
    p[i], c[i] = list(map(int, input().split()))

def dfs(s):
    if len(s) == D:
        ans = 1000
        score = 0
        times = 0
        for i in range(D):
            if s[i] == "1":
                score += 100 * (i+1) * p[i] + c[i]
                times += p[i]
        if score >= G:
            ans = min(ans, times)
        else:
            idx = s.rfind("0")
            for i in range(1, p[idx]):
                if score + 100 * (idx+1) * i >= G:
                    ans = min(ans, times+i)
                    break
        return ans
    return min(dfs(s + "0"), dfs(s+ "1"))


print((dfs("")))

# Optimized solution
def main():
    D, G = list(map(int, input().split()))
    info = [tuple(map(int, input().split())) for _ in range(D)]

    ans = 100 * 10
    for bit in range(1<<D):
        score = 0
        num_problem = 0

        # complete bonus
        for i in range(D):
            if (bit>>i) & 1:
                base = 100 * (i+1)
                score += base * info[i][0] + info[i][1]
                num_problem += info[i][0]
        # other 
        for i in range(D-1, -1, -1):
            if score >= G:
                break
            
            if not((bit>>i) & 1):
                base = 100 * (i+1)
                rest = G - score
                need = (rest + base - 1) // base

                if need > info[i][0] - 1:
                    score += base * (info[i][0] - 1)
                    num_problem += (info[i][0] - 1)
                else:
                    score += base * need
                    num_problem += need
                    break
        
        if score >= G:
            ans = min(ans, num_problem)

    print(ans)


if __name__ == "__main__":
    main()
# Original solution
def main():
    D, G = list(map(int, input().split()))
    info = [tuple(map(int, input().split())) for _ in range(D)]

    ans = 100 * 10
    for bit in range(1<<D):
        score = 0
        num_problem = 0

        # complete bonus
        for i in range(D):
            if (bit>>i) & 1:
                base = 100 * (i+1)
                score += base * info[i][0] + info[i][1]
                num_problem += info[i][0]
        # other 
        for i in range(D-1, -1, -1):
            if score >= G:
                break
            
            if not((bit>>i) & 1):
                base = 100 * (i+1)
                rest = G - score
                need = (rest + base - 1) // base

                if need > info[i][0] - 1:
                    score += base * (info[i][0] - 1)
                    num_problem += (info[i][0] - 1)
                else:
                    score += base * need
                    num_problem += need
                    break
        
        if score >= G:
            ans = min(ans, num_problem)

    print(ans)


if __name__ == "__main__":
    main()

# Optimized solution
def main():
    D, G = list(map(int, input().split()))
    info = [tuple(map(int, input().split())) for _ in range(D)]

    ans = 100 * 10
    for bit in range(1<<D):
        score = 0
        num_problem = 0

        # complete bonus
        for i in range(D):
            if (bit>>i) & 1:
                base = 100 * (i+1)
                score += base * info[i][0] + info[i][1]
                num_problem += info[i][0]
        
        # other
        if score >= G:
            ans = min(ans, num_problem)
        else:
            for i in range(D-1, -1, -1):
                if not((bit>>i) & 1):
                    rest = G - score
                    base = 100 * (i+1)
                    need = (rest + base -1) // base
                    if need <= info[i][0] - 1:
                        num_problem += need
                        score += base * need
                        ans = min(ans, num_problem)
                    break

    print(ans)


if __name__ == "__main__":
    main()
# Original solution
#!/usr/bin/env python3
import sys, math, itertools, heapq, collections, bisect, string, copy
input = lambda: sys.stdin.buffer.readline().rstrip().decode('utf-8')
sys.setrecursionlimit(10**8)
inf = float('inf')
mod = 10**9+7
ans = inf
count = 0; pro = 1

d, g = list(map(int, input().split()))
g //= 100
dp=[[inf]*(10**5*2) for i in range(11)]
dp[0][0]=0
for i in range(d):
    p,c=list(map(int,input().split()));c//=100
    for j in range(10**5*2):
        if dp[i][j]!=inf:
            dp[i+1][j]=min(dp[i+1][j],dp[i][j])
            for k in range(1,p):
                dp[i+1][j+(i+1)*k]=min(dp[i+1][j+(i+1)*k],dp[i][j]+k)
            dp[i+1][j+(i+1)*p+c] = min(dp[i+1][j+(i+1)*p+c],dp[i][j]+p)
for i in range(g,10**5*2):
    ans=min(ans,dp[d][i])
print(ans)




# for i in range(1, d+1):
#     p, c = map(int, input().split())
#     c //= 100
#     # for key, value in tuple(D.items()):
#     #     print(D[key],p)
#     #     D[key+i*p+c//100] = min(D[key+i*p+c//100], D[key]+p)
#     S = D.copy()
#     for key, value in S.items():
#         for k in range(1, p):
#             # print(D[key+i])
#             D[key+i*k] = min(D[key+i*k], S[key]+k)
#         D[key+i*p+c] = min(D[key+i*p+c], S[key]+p)
# ans = inf
# for key, value in D.items():
#     # print(key,value)
#     if key >= g:
#         ans = min(ans, value)
# print(ans)


# Optimized solution
#!/usr/bin/env python3
import sys, math, itertools, heapq, collections, bisect, string, copy
input = lambda: sys.stdin.buffer.readline().rstrip().decode('utf-8')
sys.setrecursionlimit(10**8)
inf = float('inf')
mod = 10**9+7
ans = inf
count = 0; pro = 1

d, g = list(map(int, input().split()))
g //= 100
dp=[[inf]*(10**5+10000) for i in range(11)]
dp[0][0]=0
for i in range(d):
    p,c=list(map(int,input().split()));c//=100
    for j in range(10**5+10000):
        if dp[i][j]!=inf:
            dp[i+1][j]=min(dp[i+1][j],dp[i][j])
            for k in range(1,p):
                dp[i+1][j+(i+1)*k]=min(dp[i+1][j+(i+1)*k],dp[i][j]+k)
            dp[i+1][j+(i+1)*p+c] = min(dp[i+1][j+(i+1)*p+c],dp[i][j]+p)
for i in range(g,10**5+10000):
    ans=min(ans,dp[d][i])
print(ans)




# for i in range(1, d+1):
#     p, c = map(int, input().split())
#     c //= 100
#     # for key, value in tuple(D.items()):
#     #     print(D[key],p)
#     #     D[key+i*p+c//100] = min(D[key+i*p+c//100], D[key]+p)
#     S = D.copy()
#     for key, value in S.items():
#         for k in range(1, p):
#             # print(D[key+i])
#             D[key+i*k] = min(D[key+i*k], S[key]+k)
#         D[key+i*p+c] = min(D[key+i*p+c], S[key]+p)
# ans = inf
# for key, value in D.items():
#     # print(key,value)
#     if key >= g:
#         ans = min(ans, value)
# print(ans)
# Original solution
d,g = list(map(int,input().split()))
li = [list(map(int,input().split())) for i in range(d)]

for i in range(d):
  li[i].append(li[i][0]*100*(i+1) + li[i][1])
tmp = 10 ** 9
def func(x,lis,cnt):
  global tmp
  if x <= 0:
    return cnt
  else:
    for i in range(d):
      if i not in lis:
        if x <= 100*(i+1)*(li[i][0]-1):
          tmp = min(tmp,cnt + (x-1)//(100*(i+1)) + 1)
          #print("{} {} {}".format(i,lis,tmp))
        elif x <= li[i][2]:
          tmp = min(tmp,cnt + li[i][0])
          #print("{} {} {}".format(i,lis,tmp))
        else:
          tmp = min(tmp,func(x-li[i][2],lis+[i],cnt+li[i][0]))
          #print("{} {} {}".format(i,lis,tmp))
    return tmp
print((func(g,[],0)))

# Optimized solution
d,g = list(map(int,input().split()))
li = [list(map(int,input().split())) for i in range(d)]

ans = 10 ** 9
for i in range(2**d):
  ch = bin(i)[2:]
  ch = ch.zfill(d)
  tmpsum = 0
  cnt = 0
  for j in range(d):
    if ch[j] == "1":
      tmpsum += li[j][0]*100*(j+1) + li[j][1]
      cnt += li[j][0]
  if tmpsum >= g:
    ans = min(ans,cnt)
    #print("{} {}".format(bin(i),cnt))
  else:
    ind = ch.rfind("0")
    if tmpsum + (li[ind][0]-1)*100*(ind+1) >= g:
      ans = min(ans,cnt+(g-tmpsum-1)//(100*(ind+1))+1)
      #print("{} {} {}".format(bin(i),cnt,ans))
print(ans)
# Original solution
import itertools

d,g=list(map(int,input().split()))
p=[0 for _ in range(d)]
c=[0 for _ in range(d)]
l=[[] for _ in range(d)]

for i in range(d):#値を取得！
	p[i],c[i]=list(map(int,input().split()))

for i in range(d):#リストつくる！
	for j in range(p[i]+1):
		l[i].append((i+1)*100*j)
	l[i][p[i]] += c[i]

r = list(itertools.product(*l))
m = len(r)
for i in r:
	if sum(i)>=g:
		count = 0
		for j in range(d):
			count += l[j].index(i[j])
		if count <= m:
			m = count
print(m)

# Optimized solution
d,g=list(map(int,input().split()))
p=[0 for _ in range(d)]
c=[0 for _ in range(d)]
ans = 100**10

for i in range(d):#値を取得！
	p[i],c[i]=list(map(int,input().split()))

for i in range(2**d):
	score = 0
	count = 0
	horyu = 0
	for j in range(d):
		if ((i >> j) & 1):
			score += (j+1)*p[j]*100 + c[j]
			count += p[j]
		else:
			horyu = j #あとまわし(最高点数の1種類)
	for i in range(p[horyu]):
		if score >= g and count < ans:
			ans = count
		score += (horyu + 1) * 100
		count += 1

print(ans)
# Original solution
# encoding: utf-8
D_MAX = 10
P_MAX = 100

num_and_pnt = lambda x: [int(x[0]), int(x[1]) // 100]
D, G = num_and_pnt(input().split())
# [pi, ci]
pc = [num_and_pnt(input().split()) + [i] for i in range(D)]
# pc.sort(key=lambda x: -((x[2] + 1) * x[0] + x[1]))

# depth-first-like search
G_tab = [(x[2] + 1) * x[0] + x[1] for x in pc]
cnt_tab = [x[0] for x in pc]
G_stack = G_tab[0]
cnt_stack = cnt_tab[0]
order = [0]

mincnt = D_MAX * P_MAX
while True:
    ## deepth increament (continue)
    if G_stack < G:
        # append lowest item (always break?)
        for i in range(D):
            if i not in order: break
        order.append(i)
        G_stack += G_tab[i]
        cnt_stack += cnt_tab[i]
        continue
    ## skip check
    idx_tmp = order[-1]
    G_tmp = G_stack - G_tab[idx_tmp]
    cnt_tmp = cnt_stack - cnt_tab[idx_tmp]
    if cnt_tmp < mincnt:
        ## evaluate cnt_last
        x = pc[order[-1]]
        cnt_last = x[0]
        for i in range(x[0]):
            cnt_last -= 1
            G_last = (x[2] + 1) * cnt_last
            # print("##", cnt_last, G_tmp + G_last, G)
            if G_tmp + G_last < G: break
        cnt_last += 1
        ## update mincnt
        # print("#", order, cnt_tmp, cnt_last, G - G_tmp, "/", mincnt)
        if cnt_tmp + cnt_last < mincnt: mincnt = cnt_tmp + cnt_last
    ## next node
    order_last = order[-1] + 1
    while True:
        if order_last > D - 1:
            idx_tmp = order[-1]
            G_stack -= G_tab[idx_tmp]
            cnt_stack -= cnt_tab[idx_tmp]
            order.pop()
            if len(order) < 1: break # end
            order_last = order[-1] + 1
            continue
        elif order_last in order:
            order_last = order_last + 1
            continue
        else:
            idx_tmp = order[-1]
            G_stack += (G_tab[order_last] - G_tab[idx_tmp])
            cnt_stack += (cnt_tab[order_last] - cnt_tab[idx_tmp])
            order[-1] = order_last
            break
    ## escape
    if len(order) < 1: break # end

print(mincnt)

# Optimized solution
# encoding: utf-8
D_MAX = 10
P_MAX = 100

num_and_pnt = lambda x: [int(x[0]), int(x[1]) // 100]
D, G = num_and_pnt(input().split())
# [pi, ci]
pc = [num_and_pnt(input().split()) for i in range(D)]

G_list = [(i + 1) * x[0] + x[1] for i, x in enumerate(pc)]
cnt_list = [x[0] for i, x in enumerate(pc)]
idx = [list(map(int, format(i, "b"))) for i in range(2 ** D)]

# i, G_comp, cnt_comp
table = [ (i, sum([((i // (2 ** j)) % 2) * G_list[j] for j in range(D)]), sum([((i // (2 ** j)) % 2) * cnt_list[j] for j in range(D)])) for i in range(2 ** D)] # very long
# print(table)
mincnt = D_MAX * P_MAX
for i, (G_last, cnt_last) in enumerate(zip(G_list, cnt_list)):
    for j, G_comp, cnt_comp in [x for x in table if (((x[0] // (2 ** i)) % 2 == 0) and (x[1] <= G < x[1] + G_last) and (x[2] < mincnt))]:
        # print(i, (G_last, cnt_last), j, G_comp, cnt_comp)
        cnt_last_tmp = min((-((G_comp - G) // (i + 1)), cnt_last))
        if cnt_comp + cnt_last_tmp < mincnt: mincnt = cnt_comp + cnt_last_tmp

print(mincnt)
# Original solution
# coding:utf-8

INF = float('inf')


def inpl(): return list(map(int, input().split()))


D, G = inpl()
P, C = [], []
for i in range(D):
    p, c = inpl()
    P.append(p)
    C.append(c + 100 * (i + 1) * p)

ans = INF
for i in range(2 ** D):
    point = 0
    cnt = 0
    rest_max = 0
    for shift in range(D):
        if i >> shift & 1:
            cnt += P[shift]
            point += C[shift]
        else:
            rest_max = shift

    if point < G:
        for j in range(P[rest_max]):
            if point >= G:
                break
            cnt += 1
            point += (rest_max + 1) * 100
        else:
            continue

    ans = min(ans, cnt)

print(ans)


# Optimized solution
# coding:utf-8

import sys

INF = float('inf')
MOD = 10 ** 9 + 7

def LI(): return [int(x) for x in sys.stdin.readline().split()]
def LI_(): return [int(x)-1 for x in sys.stdin.readline().split()]
def LS(): return sys.stdin.readline().split()
def II(): return int(sys.stdin.readline())
def SI(): return eval(input())


# mathを使わない切り上げ
def ceil(n, m):
    return -(-n//m)


d, g = LI()
contest = [LI() for _ in range(d)]

ans = INF

# Bit全探索
for bit in range(1 << d):
    score = 0
    cnt = 0
    remain_max = -1

    # 各bitが立っているか確認
    for i in range(d):
        if bit >> i & 1:
            score += contest[i][0] * (i + 1) * 100 + contest[i][1]
            cnt += contest[i][0]
            continue
        # コンプリートしなかった問題の中で最も得点の高い問題をメモ
        remain_max = i

    if score >= g:
        ans = min(ans, cnt)
        continue

    need = ceil((g - score) // 100, remain_max + 1)

    if need >= contest[remain_max][0]:
        continue

    ans = min(ans, cnt + need)

print(ans)