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 (Python):



from math import ceil

D, G = [int(t) for t in input().split()]
p = []
c = []
for i in range(D):
    p_, c_ = [int(t) for t in input().split()]
    p.append(p_)
    c.append(c_)

def solve(G, i):
    """100i点以下の問題だけでGを達成する最小問題数"""
    if i <= 0:
        return float('inf')
    n = min(ceil(G / (100 * i)), p[i-1])
    s = 100 * i * n
    if n == p[i-1]:
        s += c[i-1]
    if G > s:
        n += solve(G - s, i - 1)
    return min(n, solve(G, i - 1))

print(solve(G, D))

Solution (Python):
from itertools import permutations

d, g = map(int, input().split())
g = g // 100
p = []
c = []

for _ in range(d):
	pp, cc = map(int, input().split())
	p.append(pp)
	c.append(cc // 100)

ans = float("inf")
for array in permutations(range(d)):
	gap = g
	num = 0
	for a in array:
		if p[a] * (a + 1) >= gap:
			num += (gap - 1) // (a + 1) + 1
			break
		elif p[a] * (a + 1) + c[a] >= gap:
			num += p[a]
			break
		else:
			num += p[a]
			gap -= p[a] * (a + 1) + c[a]

	if num < ans:
		ans = num

print(ans)

Solution (Python):
def main():
    d, g = map(int, input().split())
    p, c = [0 for i in range(d)], [0 for i in range(d)]
    for i in range(d):
        p[i], c[i] = map(int, input().split())

    min_p = 1001
    for i in range(2**d):
        s = 0
        max_s, t = -1, 0
        for j in range(d):
            if (i >> j) & 1:
                s += p[j] * (j+1) * 100 + c[j]
                t += p[j]
            else:
                max_s = j + 1

        if g <= s:
            min_p = min(t, min_p)
        elif max_s != -1 and (g-s) // (max_s*100) < p[max_s-1]:
            t += (g-s+max_s*100-1) // (max_s*100)
            min_p = min(t, min_p)

    print(min_p)


if __name__ == '__main__':
    main()

Solution (Python):
from itertools import product
from math import ceil
n,k=map(int,input().split())
A=[]
for i in range(1,n+1):
  a,b=map(int,input().split())
  A+=[(a,i*100,a*i*100+b)]

ans=1e9
for p in product([0,1],repeat=n):
  s=0
  c=0
  m=0
  for i,j in enumerate(p):
    if j==1:
      c+=A[i][0]
      s+=A[i][2]
    else:
      m=max(m,i)
  if s>=k:
    ans=min(ans,c)
  else:
    if (k-s)/A[m][1]<A[m][0]:
      ans=min(ans,c+ceil((k-s)/A[m][1]))
print(ans)

Solution (Python):
d, g = [int(i) for i in input().split()]
A, B = zip(*[[int(i) for i in input().split()] for j in range(d)])

D = [0] * 10
ans = 10 ** 3

for bit in range(1, 2**10+1):
    score = 0
    cnt = 0
    for i in range(d):
        if bit >> i & 1:
            score += A[i] * (i+1) * 100 + B[i]
            cnt += A[i]

    if not score >= g:
        for i in range(d-1, -1, -1):
            if not bit >> i & 1:
                for j in range(A[i]):
                    score += (i+1) * 100
                    cnt += 1
                    if score >= g:
                        break
                else:
                    continue
                break

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

print(ans)

Solution (Python):
from itertools import combinations

def exclude_combi_idx(combis, scores):
    a = [score[1] for score in combis]
    v = []
    for score in scores:
        if score[1] in a:
            continue
        v.append(score)
    return v

def set_all_solve(combi):
    current = 0
    num = 0
    for item in combi:
        num += item[0]
        current += item[2]
    return num, current

def track_residue(num, score, current, target):
    for i in range(num):
        current += score
        if current >= target:
            return i + 1
    return None

def main():
    D, G = [int(c) for c in input().split()]
    items = []
    for idx in range(1, 1+D):
        num, bonasu = [int(c) for c in input().split()]
        items.append((idx * 100, num, bonasu))
    scores = [(num, idx,idx * num + bonasu) for idx, num, bonasu in items]
    max_prob = sum([num for num,_, _ in scores])
    min_prob = max_prob
    for i in range(0, D+1):
        combis = list(combinations(scores, i))
        
        for combi in combis:
            s = 0
            prob = 0
            
            tmp, tmp2 = set_all_solve(combi)
            prob += tmp
            s += tmp2
            
            if s >= G:
                if prob < min_prob:
                    min_prob = prob
                    continue
            else:
                v = exclude_combi_idx(combi, scores)[-1] 
                res = track_residue(v[0], v[1], s, G)
                if res is None:
                    continue
                if res + prob < min_prob:
                    
                    min_prob = res + prob
    print(min_prob)

if __name__ == '__main__':
    main()

Solution (Python):
d,g = map(int,input().split())
pc = [list(map(int,input().split()))for _ in[0]*d]
ans = []
for mask in range(1 << d):
    s = 0
    num = 0
    rest_max = -1
    for i in range(d):
        p,c = pc[i]
        if mask >> i & 1:
            s += p * 100 * (i + 1) + c
            num += p
        else:
            rest_max = i
    if s < g:
        s1 = 100 * (rest_max + 1)
        need = (g - s + s1 - 1) // s1
        if need >= pc[rest_max][0]:
            continue
        num += need
    ans.append(num)
print(min(ans))

Solution (Python):

import bisect
import heapq
import math
import random
import sys
from collections import Counter, defaultdict, deque
from decimal import ROUND_CEILING, ROUND_HALF_UP, Decimal
from functools import lru_cache, reduce
from itertools import combinations, combinations_with_replacement, product, permutations
from operator import add, mul

sys.setrecursionlimit(10000)


def read_int():
    return int(input())


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


def read_float():
    return float(input())


def read_float_n():
    return list(map(float, input().split()))


def read_str():
    return input()


def read_str_n():
    return list(map(str, input().split()))


def error_print(*args):
    print(*args, file=sys.stderr)


def mt(f):
    import time

    def wrap(*args, **kwargs):
        s = time.time()
        ret = f(*args, **kwargs)
        e = time.time()

        error_print(e - s, 'sec')
        return ret

    return wrap


@mt
def slv(D, G, PC):

    ans = sys.maxsize
    PC = list(reversed(PC))
    for i in product([0, 1], repeat=D):
        g = G
        p = 0
        for j, v in enumerate(i):
            if v == 0:
                continue
            p += PC[j][0]
            g -= PC[j][1] + PC[j][0] * (D-j) * 100
        if g > 0 and 0 in i:
            j = i.index(0)
            for _ in range(PC[j][0]-1):
                p += 1
                g -= (D-j)*100
                if g <= 0:
                    break
        if g <= 0:
            ans = min(ans, p)

    return ans


def main():
    D, G = read_int_n()
    PC = [read_int_n() for _ in range(D)]
    print(slv(D, G, PC))


if __name__ == '__main__':
    main()

Solution (Python):


d,g = map(int, input().split())
P = []
C = []
sums = []
for i in range(d):
    p,c = map(int, input().split())
    P.append(p)
    C.append(c)
    sums.append(p * 100 * (i+1) + c)

ans = 1e9
for mask in range(1 << d):
    score = 0
    num = 0
    rest_max = -1
    for i in range(d):
        if mask >> i & 1:
            score += sums[i]
            num += P[i]
        else:
            rest_max = i
    if score < g:
        tmp = 100 * (rest_max + 1)
        need = (g - score + tmp - 1) // tmp
        if need >= P[rest_max]: continue
        num += need
    ans = min(ans, num)

print(ans)

Solution (Python):
d,g = map(int,input().split())
 
p = []
 
for i in range(d):
    p.append(list(map(int,input().split())))

from itertools import product
from math import ceil
 
ans = 1e09
 
for c in product([0,1],repeat=d):
    score = 0
    num = 0
    ind = 0
    for i in range(d):
        if c[i] == 1:
            score += p[i][0]*100*(i+1) + p[i][1]
            num += p[i][0]
        else:
            ind = max(i,ind)
    
    if g - score <= 0:
        ans = min(ans,num)
    elif g - score <= (p[ind][0]-1)*100*(ind+1):
        num += ceil((g-score)/(100*(ind+1)))
        ans = min(ans,num)
print(ans)

Solution (Python):
def c_all_green(D, G, Problems):
    ans = float('inf')
    for binary in range(1 << D):
        total_score = 0
        solved_problem = 0
        
        
        for k, (p, c) in enumerate(Problems):
            if binary & (1 << k) != 0:
                total_score += 100 * p * (k + 1) + c
                solved_problem += p

        
        
        if G <= total_score:
            ans = min(ans, solved_problem)
            continue

        
        for k, (p, c) in enumerate(reversed(Problems), 1):  
            if binary & (1 << (D-k)) != 0:
                continue  
            for _ in range(p):
                if G <= total_score:
                    break
                total_score += 100*(D-k+1)
                solved_problem += 1

        ans = min(ans, solved_problem)
    return ans

D, G = [int(i) for i in input().split()]
Problems = [[int(i) for i in input().split()] for j in range(D)]
print(c_all_green(D, G, Problems))

Solution (Python):
from collections import deque

def solve(count, i, g, pcs, rem):
    if g <= 0:
        return count
    if pcs == []:
        index, p = rem
        if index == 0:
            return count
        plus = g // (100 * index) + (1 if g % (100 * index) != 0 else 0)
        return count + plus if plus < p else float("Inf")
    p, c = pcs[0]
    l = pcs[1:]
    a = solve(count, i + 1, g, l, (i, p))
    b = solve(count + p, i + 1, g - c - 100 * i * p, l, rem)
    return a if a < b else b



if __name__ == "__main__":
    d, g = map(int, input().split())
    pcs = [tuple(int(s) for s in input().split()) for _ in range(d)]
    print(solve(0, 1, g, pcs, (0, 0)))

Solution (Python):
from itertools import permutations, product
from math import ceil, floor

D, G = [int(elem) for elem in input().split(' ')]
point_info_list = [[int(elem) for elem in input().split()] for _ in range(D)]
assert len(point_info_list) == D
assert len(point_info_list[0]) == 2


""" min_num = float('inf')
for perm in permutations(range(D)):
    current_point = 0
    current_num = 0
    for point in perm:
        if (G - current_point) - (point + 1) * 100 * point_info_list[point][0] <= 0:
            current_num += ceil((G - current_point) / ((point + 1) * 100))
            break
        elif (G - current_point) - (point + 1) * 100 * point_info_list[point][0] - point_info_list[point][1] <= 0:
            current_num += point_info_list[point][0]
            break
        else:
            current_point += (point + 1) * 100 * point_info_list[point][0] + point_info_list[point][1]
            current_num += point_info_list[point][0]
    min_num = min(current_num, min_num)

print(min_num)
 """


min_num = float('inf')
for mask in product([False, True], repeat=D):
    chosen_indices = [i for i, chosen in enumerate(mask) if chosen]
    current_point = 0
    current_num_solved = 0
    for chosen_index in chosen_indices:
        point = (chosen_index + 1) * 100
        num_problems = point_info_list[chosen_index][0]
        bonus = point_info_list[chosen_index][1]
        current_point += point * num_problems + bonus
        current_num_solved += num_problems

    if current_point >= G:
        min_num = min(min_num, current_num_solved)
    else:
        chosen_indices = set(chosen_indices)
        max_index = max([i for i in range(D) if i not in chosen_indices])
        point = (max_index + 1) * 100
        num_problems = point_info_list[max_index][0]
        if current_point + point * num_problems < G:
            continue
        else:
            current_num_solved += ceil((G - current_point) / point)
            min_num = min(min_num, current_num_solved)

print(min_num)

Solution (Python):
inputs = input().strip().split()
D = int(inputs[0])
G = int(inputs[1])

pi = []
ci = []

for i in range(0, D):
    inputs = input().strip().split()
    pi.append(int(inputs[0]))
    ci.append(int(inputs[1]))

bitArray = []
for i in range(0, pow(2, D)):
    bitArray.append(format(i, 'b').zfill(D))

ans = 1000000
for bit in bitArray:
    num = 0
    score = 0
    for index, value in enumerate(bit):
        if value is "1":
            score += (index + 1) * 100 * pi[index] + ci[index]
            num += pi[index]
        else:
            max_zero_index = index  
    for i in range(0, pi[max_zero_index] - 1):
        if score < G:
            num += 1
            score += (max_zero_index + 1) * 100
    if ans > num and score >= G:
        ans = num

print(ans)

Solution (Python):
D, G = map(int, input().split())
pcs = [[i] + list(map(int, input().split())) for i in range(1, D + 1)]
from itertools import product
ans = 10 ** 10
for bonus in product(range(2), repeat=D):
    sum_b = 0
    cnt = 0
    for b, (i, p, c) in zip(bonus, pcs):
        if b:
            sum_b += c + i * 100 * p
            cnt += p

    if sum_b >= G:
        ans = min(ans, cnt)

    else:
        for b, (i, p, c) in reversed(list(zip(bonus, pcs))):
            if b:
                continue

            rem = -(-(G - sum_b) // (i * 100))
            sum_b += min(rem, p) * i * 100
            cnt += min(rem, p)
            if sum_b >= G:
                break

        ans = min(ans, cnt)

print(ans)

Solution (Python):
import random
import bisect
import math

option = 0     
max_or_min = 0 

iter=2

N = 50 
T = 1000 
maximum=1
minimum=0

dimension, limit = [int(i) for i in input().split()]

pi = [0 for i in range(dimension)]
ci = [0 for i in range(dimension)]
       
for i in range(dimension):
    pi[i], ci[i] = [int(i) for i in input().split()]

tot = [pi[i] * (i+1) * 100 + ci[i] for i in range(dimension)]








def criterion(x):
    
    z = sum([pi[i] * x[i] for i in range(dimension)])
    z2 = sum([tot[i] * x[i] for i in range(dimension)])
    k = -1
    for i in range(dimension):
      if x[dimension -1 -i] == 0:
        k = dimension -1 -i
        break
    if k != -1:
      for i in range(pi[k]):
        if limit > z2:
          z += 1
          z2 +=  (k+1) * 100
        else:
          break

    if limit > z2:
        z = 10000
    return z


def update_position(x, v, x_min, x_max):

    new_x = [1 if random.uniform(0, 1)< 1/(1+math.e**(-v[i])) else 0 for i in range(dimension)]
    return new_x


def update_velocity(x, v, p, g, w, ro_max=1.0, c1=2.00, c2=0.75):
    
    phi=c1+c2
    K=2/abs(2-phi-(phi*phi-4*phi)**0.5)
    
    
    if option!=0:
        new_v = [K * ( w * v[i] + c1 * random.uniform(0, ro_max) * (p[i] - x[i]) + c2 * random.uniform(0, ro_max) * (g[i] - x[i]) ) for i in range(dimension)]
    else:
        new_v = [w * v[i] + c1 * random.uniform(0, ro_max) * (p[i] - x[i]) + c2 * random.uniform(0, ro_max) * (g[i] - x[i]) for i in range(dimension)]

    return new_v

def main():
    w = 1.0
    w_best, w_worst = 1.25, 0.25
    x_min = [minimum for i in range(dimension)]
    x_max = [maximum for i in range(dimension)]
    
    
    ps = [[random.randint(x_min[j], x_max[j]) for j in range(dimension)] for i in range(N)]
    vs = [[0.0 for j in range(dimension)] for i in range(N)]

    personal_best_positions = ps[:] 
    personal_best_scores = [criterion(p) for p in ps]

    if max_or_min == 1:
        best_particle = personal_best_scores.index(max(personal_best_scores))
    elif max_or_min == 0:
        best_particle = personal_best_scores.index(min(personal_best_scores))
    global_best_position = personal_best_positions[best_particle][:]

    for t in range(T):
        for n in range(N):
            x = ps[n][:]
            v = vs[n][:]
            p = personal_best_positions[n][:]

            if option>=2:
                best_list = sorted(personal_best_positions)
                mu = bisect.bisect_left( best_list, p ) + 1
                w = w_best - mu * (w_best - w_worst) / (N - 1)


            
            new_x = update_position(x, v, x_min, x_max)
            ps[n] = new_x[:]

            
            new_v = update_velocity(new_x, v, p, global_best_position, w)
            vs[n] = new_v[:]

            
            score = criterion(new_x)

            if max_or_min == 1:
                if score > personal_best_scores[n]:
                    personal_best_scores[n] = score
                    personal_best_positions[n] = new_x[:]
            elif max_or_min == 0:
                if score < personal_best_scores[n]:
                    personal_best_scores[n] = score
                    personal_best_positions[n] = new_x[:]

        
        if max_or_min == 1:
            best_particle = personal_best_scores.index(max(personal_best_scores))
            global_best_position = personal_best_positions[best_particle][:]

        elif max_or_min == 0:
            best_particle = personal_best_scores.index(min(personal_best_scores))
            global_best_position = personal_best_positions[best_particle][:]
                     
        f.write(str(max(personal_best_scores))+"\n")
    
    if max_or_min == 1:
        return max(personal_best_scores)
    elif max_or_min == 0:
        return min(personal_best_scores)


with open('test_'+ str(option)+".txt", 'w') as f:
    
  if max_or_min == 1:
    best=-float("inf")
    for i in range(iter):
        best=max(best, main())

  elif max_or_min == 0:
    best=float("inf")
    for i in range(iter):
        best=min(best, main())

print(best)

Solution (Python):
import random
import bisect
import math

option = 0     
max_or_min = 0 

iter=3

N = 50 
T = 1000 
maximum=1
minimum=0

dimension, limit = [int(i) for i in input().split()]

pi = [0 for i in range(dimension)]
ci = [0 for i in range(dimension)]
       
for i in range(dimension):
    pi[i], ci[i] = [int(i) for i in input().split()]

tot = [pi[i] * (i+1) * 100 + ci[i] for i in range(dimension)]








def criterion(x):
    
    z = sum([pi[i] * x[i] for i in range(dimension)])
    z2 = sum([tot[i] * x[i] for i in range(dimension)])
    k = -1
    for i in range(dimension):
      if x[dimension -1 -i] == 0:
        k = dimension -1 -i
        break
    if k != -1:
      for i in range(pi[k]):
        if limit > z2:
          z += 1
          z2 +=  (k+1) * 100
        else:
          break

    if limit > z2:
        z = 10000
    return z


def update_position(x, v, x_min, x_max):

    new_x = [1 if random.uniform(0, 1)< 1/(1+math.e**(-v[i])) else 0 for i in range(dimension)]
    return new_x


def update_velocity(x, v, p, g, w, ro_max=1.0, c1=2.00, c2=0.75):
    
    phi=c1+c2
    K=2/abs(2-phi-(phi*phi-4*phi)**0.5)
    
    
    if option!=0:
        new_v = [K * ( w * v[i] + c1 * random.uniform(0, ro_max) * (p[i] - x[i]) + c2 * random.uniform(0, ro_max) * (g[i] - x[i]) ) for i in range(dimension)]
    else:
        new_v = [w * v[i] + c1 * random.uniform(0, ro_max) * (p[i] - x[i]) + c2 * random.uniform(0, ro_max) * (g[i] - x[i]) for i in range(dimension)]

    return new_v

def main():
    w = 1.0
    w_best, w_worst = 1.25, 0.25
    x_min = [minimum for i in range(dimension)]
    x_max = [maximum for i in range(dimension)]
    
    
    ps = [[random.randint(x_min[j], x_max[j]) for j in range(dimension)] for i in range(N)]
    vs = [[0.0 for j in range(dimension)] for i in range(N)]

    personal_best_positions = ps[:] 
    personal_best_scores = [criterion(p) for p in ps]

    if max_or_min == 1:
        best_particle = personal_best_scores.index(max(personal_best_scores))
    elif max_or_min == 0:
        best_particle = personal_best_scores.index(min(personal_best_scores))
    global_best_position = personal_best_positions[best_particle][:]

    for t in range(T):
        for n in range(N):
            x = ps[n][:]
            v = vs[n][:]
            p = personal_best_positions[n][:]

            if option>=2:
                best_list = sorted(personal_best_positions)
                mu = bisect.bisect_left( best_list, p ) + 1
                w = w_best - mu * (w_best - w_worst) / (N - 1)


            
            new_x = update_position(x, v, x_min, x_max)
            ps[n] = new_x[:]

            
            new_v = update_velocity(new_x, v, p, global_best_position, w)
            vs[n] = new_v[:]

            
            score = criterion(new_x)

            if max_or_min == 1:
                if score > personal_best_scores[n]:
                    personal_best_scores[n] = score
                    personal_best_positions[n] = new_x[:]
            elif max_or_min == 0:
                if score < personal_best_scores[n]:
                    personal_best_scores[n] = score
                    personal_best_positions[n] = new_x[:]

        
        if max_or_min == 1:
            best_particle = personal_best_scores.index(max(personal_best_scores))
            global_best_position = personal_best_positions[best_particle][:]

        elif max_or_min == 0:
            best_particle = personal_best_scores.index(min(personal_best_scores))
            global_best_position = personal_best_positions[best_particle][:]
                     
        f.write(str(max(personal_best_scores))+"\n")
    
    if max_or_min == 1:
        return max(personal_best_scores)
    elif max_or_min == 0:
        return min(personal_best_scores)


with open('test_'+ str(option)+".txt", 'w') as f:
    
  if max_or_min == 1:
    best=-float("inf")
    for i in range(iter):
        best=max(best, main())

  elif max_or_min == 0:
    best=float("inf")
    for i in range(iter):
        best=min(best, main())

print(best)

Solution (Python):
'''
https://beta.atcoder.jp/contests/abc104/submissions/2954675
https://beta.atcoder.jp/contests/abc104/submissions/2953603
'''
D, G = map(int, input().split())
p = []
c = []
for i in range(D):
    x, y = map(int, input().split())
    p.append(x)
    c.append(y)

ans = max(p) * D
for i in range(1 << D):
    cnt = 0
    score = 0
    rest_max = -1
    for j in range(D):
        if i >> j & 1:
            score += c[j]
            score += p[j] * (j + 1) * 100
            cnt += p[j]
        else:
            rest_max = j
    if score < G:
        g = (rest_max + 1) * 100
        need = (G - score + g - 1) // g
        if need >= p[rest_max]:
            continue
        cnt += need
    ans = min(ans, cnt)
print(ans)

'''
G-score mod g: 剰余0～(g-1)
これに(g-1)を加えると
剰余は(g-1), g, ..., (2g-2) = (g+g-2)まで
元の剰余が0だった場合以外は、剰余をgで割ると1.xになるので、
整数部分を取れば、切り上げになっている
'''

Solution (Python):
d, g = list(map(int, input().split()))
pc = [list(map(int, input().split())) for _ in range(d)]

ans = 10**9
for bit in range(1<<d):
    score = 0
    n = 0
    
    for i in range(d): 
        if bit & 1<<i: 
            score += pc[i][1] + pc[i][0]*100*(i+1)
            n += pc[i][0]

    if score >= g:
        ans = min(ans, n)
    else: 
        for i in range(d-1, -1, -1): 
            if bit & 1<<i: 
                continue
            for j in range(pc[i][0]): 
                if score >= g:
                    break
                score += 100*(i+1)
                n += 1
        ans = min(ans, n)

print(ans)

Solution (Python):
d,g = map(int,input().split())

p = []

for i in range(d):
    p.append(list(map(int,input().split())))

from itertools import product
from math import ceil

ans = 1e09

for c in product([0,1],repeat=d):
    score = 0
    num = 0
    ind = 0
    for i in range(d):
        if c[i] == 1:
            score += p[i][0]*100*(i+1) + p[i][1]
            num += p[i][0]
        else:
            ind = max(i,ind)
    
    if g - score <= 0:
        ans = min(ans,num)
    elif g - score <= (p[ind][0]-1)*100*(ind+1):
        num += ceil((g-score)/(100*(ind+1)))
        ans = min(ans,num)
print(ans)

Solution (Python):
from sys import exit, setrecursionlimit, stderr
from functools import reduce
from itertools import *
from collections import defaultdict
from bisect import bisect
 
def read():
  return int(input())
 
def reads():
  return [int(x) for x in input().split()]

D, G = reads()
p = [0] * D; c = [0] * D
for i in range(D):
  p[i], c[i] = reads()

def subsets(s):
  return 

def divceil(a, b):
  return (a + b - 1) // b

ans = sum(p)
for sub in chain(*(combinations(range(D), r) for r in range(D))):
  rest = G - sum((i+1) * 100 * p[i] + c[i] for i in sub)
  k = max(set(range(D)).difference(sub))
  if rest <= p[k] * (k+1) * 100:
    n = max(divceil(rest, (k+1) * 100), 0)
    ans = min(ans, sum(p[i] for i in sub) + n)
print(ans)

Solution (Python):
D, G = map(int, input().split())
pc = [[i + 1] + [int(x) for x in input().split()] for i in range(D)]

import math
m = {}
def f(cur, n, left):
    if left <= 0:
        return n
    def g(cur, n, left):
        if cur in m: return m[cur]
        r = m[cur] = f(cur, n, left)
        return r
    ret = 10**9
    for x in pc:
        i, p, c = x
        if (1 << i) & cur: continue
        ip = i*100*p
        if ip > left:
            h = math.ceil(left / (i*100))
            ret = min(ret, n + h)
        else:
            if n + p >= ret: continue
            h = g(cur | (1 << i), n + p, left - ip - c)
            ret = min(ret, h)
    return ret

print(f(0, 0, G))

Solution (Python):

D,G = map(int, input().split())




prob_num = []
comp = []

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

comp_point = []
for i in range(D):
    comp_point.append((100*(i+1)*prob_num[i]+comp[i]))



ans = 1000000
for b in range(1<<D):
    hasComp = []
    for j in range(D):
        if b & (1<<j):
            hasComp.append(True)
        else:
            hasComp.append(False)
        
    
    point = 0
    prb = 0
    for i in range(D):
        if hasComp[i]:
            point += comp_point[i]
            prb += prob_num[i]
    
    res = G-point
    
    while res>0:
        flag = 0
        for i in range(D-1,-1,-1):
            if not hasComp[i]:
                if res <= (100*(i+1)*(prob_num[i]-1)):
                    req_prob = (res//(100*(i+1))) + bool(res%(100*(i+1)))
                    prb += req_prob
                    res = 0
                    break
                
                else:
                    prb += (prob_num[i]-1)
                    res -= (100*(i+1))*(prob_num[i]-1)
        
            if i==0:
                flag = 1
                break
        
        if flag:
            break
    if res<=0:
        ans = min(ans,prb)
    
print(ans)

Solution (Python):
import sys

D, G = map(int, input().split())
pc = []
for i in range(D):
    pc.append(list(map(int, input().split())))


ans = sys.maxsize
for i in range(2**D):
    S = bin(i)[2:]
    for j in range(D - len(S)):
        S = "0" + S
    

    tmp_p = 0
    tmp_ans = 0
    max_k = 0
    for k in range(D):
        if(S[k:k+1] == "1"):
            tmp_p += pc[k][0] * 100 * (k + 1) + pc[k][1]
            tmp_ans += pc[k][0]
        else:
            if(max_k < k):
                max_k = k

    rest = G - tmp_p
    
    if(rest >= 0):
        t = -(-1 * rest // (100 * (max_k + 1)))
        if(t < pc[max_k][0]):
            tmp_ans += t
            if(tmp_ans < ans):
                ans = tmp_ans
    else:
        if(tmp_ans < ans):
            ans = tmp_ans

print(ans)

Solution (Python):
D,G=map(int,input().split())
table=[(0,0) for i in range(D)]
for i in range(D):
    p,c=map(int,input().split())
    table[i]=(p,c)
ans=10**9

for i in range(1<<D):
    t=G
    s=0
    for j in range(D):
        if i & (1<<j):
            s+=table[j][0]
            t=t-table[j][1]-table[j][0]*(j+1)*100
    if t<=0:
        ans=min(ans,s)
        
    else:
        j=D-1
        flag=True
        while flag and (j>=0):
            
            if not (i & (1<<j)):
                for u in range(table[j][0]-1):
                    if t<=0:
                        flag =False
                        break
                    else:
                        s+=1
                        t-=100*(j+1)
            j-=1
        if t<=0:
            ans=min(ans,s)
print(ans)

Solution (Python):
d, g = [int(v) for v in input().split()]
p = []
c = []
sums = []
for i in range(d):
    tmp = [int(v) for v in input().split()]
    p.append(tmp[0])
    c.append(tmp[1])
    sums.append(tmp[0] * 100 * (i+1) + tmp[1])

ans = 1e9
for mask in range(1 << d):
    s = 0
    num = 0
    rest_max = -1
    for i in range(d):
        if (mask >> i & 1) == 1:
            s += sums[i]
            num += p[i]
        else:
            rest_max = i
    if s < g:
        s1 = 100 * (rest_max + 1)
        need = (g - s + s1 - 1) // s1
        if need >= p[rest_max]:
            continue
        num += need
    ans = min(ans, num)

print(ans)