백준
작성 수정
2021년 11월부터 2022년 3월까지 solved.ac Class 1, 2, 3 문제를 푼 것이다. 문제 번호 순서로 둔다. 1003 피보나치 함수와 1260 DFS 와 BFS 가 Class 3 이고 나머지는 Class 1, 2 다. 풀이 위아래의 주석은 그때 적은 것인데, 완전탐색을 먼저 떠올리지 못해 막혔던 이야기가 1436 영화감독 숌과 18111 마인크래프트에 있고, 2805 나무 자르기에는 Counter 를 쓰자 3036ms 가 456ms 로 줄었다는 기록이 있다.
1003 피보나치 함수
# dp문제, 부분해는 전체해가 된다.
n = int(input())
count_zero =[1,0,1]
count_one = [0,1,1]
def fibo(num):
length = len(count_zero)
if length <= num:
for i in range(length, num+1):
count_zero.append(count_zero[i-1]+count_zero[i-2])
count_one.append(count_one[i-1]+count_one[i-2])
print(count_zero[num], count_one[num])
for i in range(n):
num = int(input())
fibo(num)
# 내가 푼 것
n = int(input())
zero =[1, 0, 1]
one = [0, 1, 1]
for i in range(n):
num = int(input())
length = len(zero)
if length <= num:
for j in range(length, num+1):
zero.append(zero[j-1] + zero[j-2])
one.append(one[j-1] + one[j-2])
print(zero[num],one[num])
1018 체스판 다시 칠하기
처음 풀이. 슬라이싱 li[i:i+8][j:j+8] 이 열을 자르지 못한다는 것을 배웠다
# 완전탐색 문제? 8 < n,m < 50
# 체스판에 맞춰서 다시 칠하기
n,m = map(int,input().split())
li=[(list(input())) for _ in range(n)]
# 최대한 블랙/화이트 연속이 많은 쪽으로 자르기
# 여기서 컴퓨팅적 사고를 입히면..... ! 유레카 -> 컴퓨팅적 사고란 최대한 많은 횟수를 진행해보고 판단하는 것
# 8칸*8칸씩 끊어서 체스판에 맞게 출력하기 위한 횟수 중 최소값을 리턴하면 되겠네
wb = ['W','B','W','B','W','B','W','B']
bw = ['B','W','B','W','B','W','B','W']
poss1 = [wb,bw,wb,bw,wb,bw,wb,bw]
poss2 = [bw,wb,bw,wb,bw,wb,bw,wb]
count_li = []
# 시간복잡도 계산, (42 * 42 * 8 * 8) * 2 160,000
# 하나씩 대입하지 않고, 슬라이싱으로 하는 법도 있구나!
for i in range(0, n-8+1):
for j in range(0, m-8+1):
# for p in range(8):
# for q in range(8):
new_li = li[i:i+8][j:j+8]
count1 = 0
count2 = 0
for p in range(8):
for q in range(8):
print(new_li)
if poss1[p][q] == new_li[p][q]:
pass
else:
count1+=1
if poss2[p][q] == new_li[p][q]:
pass
else:
count2+=1
count_li.append(count1)
count_li.append(count2)
print(min(count_li))
# li[0:1]은 리스트 형이기 때문입니다.
# 빈 리스트에 0:1의 원소를 하나씩 추가합니다.
# 0:1이니까 인덱스 0의 원소만 추가하죠.
# li[0:1][0:2] 해도 열의 슬라이싱은 무시하고 li[0]의 원소 그대로 가져온다
다른 풀이. 홀수 칸과 짝수 칸만 본다
# 굳이 리스트에 넣어서 확인하지 않아도 되는 문제
# 체스판의 성질을 이용하여, 홀수냐 짝수냐(%2)만 판별하면 파악할 수 있음
n,m = map(int,input().split())
li=[(list(input())) for _ in range(n)]
count = []
for i in range(n-8+1):
for j in range(m-8+1):
count1 = 0
count2 = 0
# 체크
# 체크판 하나일 대 두가지 경우의 수 비교
for p in range(i,i+8):
for q in range(j,j+8):
# case1) 홀수B 짝수W
# case2) 짝수B 홀수W
# 짝수쪽 위치일 때
if (p+q)%2 ==0:
if li[p][q] == 'W':
count2 += 1
if li[p][q] == 'B':
count1 += 1
# 홀수쪽 위치일 때
else:
if li[p][q] == 'W':
count1 +=1
if li[p][q] == 'B':
count2 +=1
count.append(min(count1,count2))
print(min(count))
1260 DFS와 BFS
참고 풀이
def DFS(v):
print(v,end='')
visit[v] = 1
for i in range(1, n+1):
if visit[i] == 0 and s[v][i] == 1:
DFS(i)
def BFS(v):
queue = [v]
visit[v] = 1
while(queue):
v = queue[0]
print(v, end='')
del queue[0]
for i in range(1, n+1):
if visit[i] == 0 and s[v][i] == 1:
queue.append(i)
visit[i] = 1
n, m, v = map(int, input().split())
s = [[0] * (n+1) for i in range(n+1) ]
# 원소 개수 멀티플, [0]*(n+1) 자체를 반복
visit = [0 for i in range(n+1)]
# visit = [0] *(n+1)
for i in range(m):
x, y = map(int, input().split())
s[x][y] = 1
s[y][x] = 1
# DFS(v)
BFS(v)
내 풀이. BFS 쪽은 방문 표시를 0 과 1 을 거꾸로 써서 DFS 를 돌린 뒤의 배열을 그대로 쓴다
def DFS(v):
visit[v] = 1
print(v ,end=' ')
for i in range(n+1):
if s[v][i] == 1 and visit[i] == 0:
DFS(i)
def BFS(v):
visit[v] = 0
queue = [v]
while(queue):
v = queue[0]
print(queue[0], end=' ')
del queue[0]
for i in range(n+1):
if s[v][i] == 1 and visit[i] == 1:
queue.append(i)
visit[i] = 0
n, m, v = map(int, input().split())
s = [[0]* (n+1) for i in range(n+1) ]
visit = [0]*(n+1)
for i in range(m):
x,y = map(int,input().split())
s[x][y] = 1
s[y][x] = 1
DFS(v)
print()
BFS(v)
1316 그룹 단어 체커
"""
1) 문자열 그대로 인덱스를 활용하는 법을 활용
2) 리스트에 따로 추가하는 방식이 아닌, 이미 있는 문자열 활용
3) 반복문이 끝나는 것, break를 통해 나오는 것이 같은 연산이 될 수 있으므로, break문에서 연산을 해줌
"""
n = int(input())
count = 0
for i in range(n):
word = input()
for j in range(len(word)-1):
if word[j] == word[j+1]:
pass
elif word[j] in word[j+1:]:
count +=1
break
# 그룹단어 출력, 총 개수 - 카운트
print(n-count)
1436 영화감독 숌
# 컴퓨팅적 사고를 발현하지 못했따.
# 666이 어떻게 카운팅 되는지가 중요한 게 아니라, 시간초과가 되지 않으면
# 완전탐색으로 666을 찾는 식이 맞았다.
n = int(input())
sixes = '66'
count = 0
answer = 0
num = 66
while n!=count:
if sixes in str(num):
count += 1
answer = num
num +=1
print(answer)
'''
다른애들도 마찬가지로
666 앞에 증가하는 수를 붙인다.
666 뒤에 증가하는 수를 붙인다.
더 작은 수를 배열에 추가시킨다.
이딴식으로 처음에 접근한다.
인간의 오류는 비슷하다.
효율적인 컴퓨팅적 사고를 기르자
'''
1654 랜선 자르기
# 이분탐색 문제 적용법:
# 1) 특정 값을 찾아야 하는데, 연산 횟수가 너무 많은 것 같다. -> 이분탐색 사용 고려
# 2) 탐색이 되는 대상은 주로 특정 값을 찾는데 필요한 식의 한 부분을 차지하고 있다.
# 3) 여기선 각각의 item들을 !나누는 값!으로써 start mid end, 1부터 max(item)까지 차지하고 있다.
# 분기점 찾기
k,n = map(int, input().split())
li = [int(input()) for _ in range(k)]
start,end = 1,max(li) # 탐색 타겟은 길이, 따라서 end는 자르고자 하는 막대기중 가장 큰 것을 담는다.
while start <= end: #적절한 랜선의 길이를 찾는 알고리즘
mid = (start + end) // 2 #중간 위치
lines = 0 #랜선 수
for item in li:
lines += item // mid #분할 된 랜선 수
if lines >= n: #랜선의 개수가 분기점
start = mid + 1
else:
end = mid - 1
print(end)
from sys import stdin
K, N = map(int,stdin.readline().split())
li = list(map(int,stdin.readlines()))
h, l = sum(li)//N, 1
# h, l = max(li), 1
while l <= h :
mid = (h+l)//2
cnt = sum([x//mid for x in li])
if cnt < N:
h = mid - 1
elif cnt >= N:
l = mid + 1
ans = mid
print(ans)
# while문이든 for문이든 def가 다르지 않으면 중간에 변수 선언해도 반복문 나와지더라도 연속이 되는구나 ㄷㄷ 처음앎
1874 스택 수열
n = int(input())
s =[]
s_op=[]
answer = True
count = 1
for _ in range(n):
num = int(input())
while num >= count:
s_op.append('+')
s.append(count)
count +=1
if s[-1] == num :
s.pop()
s_op.append('-')
else:
answer = False
print("NO")
break
if answer:
for i in s_op:
print(i)
1929 소수 구하기
# 가장 중요한 d[0], d[1] 을 1로 넣지 않어서 m이 0인경우에 소수가 0과 1도 출력되는 문제가 발생했다.
import math
m,n = map(int,input().split())
d = [0 for _ in range(n+1)]
d[0] = d[1] = 1
for i in range(2,int(math.sqrt(n))+1):
# 남은 소수에 대하여
if d[i] == 0:
# 소수 배수 다 지우기, j=2 2배수 부터 시작 j=1안하는 이유가 소수는 지우면 안됨
j = 2
while i*j <=n:
d[i*j] = 1
j+=1
for i in range(m,n+1):
if d[i] == 0:
print(i)
1966 프린터 큐
처음 풀이
from collections import deque
t = int(input())
for _ in range(t):
n,m=map(int,input().split())
queue = deque(list(map(int,input().split())))
idx_queue = deque(list(range(n)))
count = 0
while queue:
if queue[0] == max(queue):
count +=1
if idx_queue[0] == m:
print(count)
break
queue.popleft()
idx_queue.popleft()
else:
queue.append(queue.popleft())
idx_queue.append(idx_queue.popleft())
다시 풀기
from collections import deque
t = int(input())
for _ in range(t):
n , x = map(int,input().split())
que = deque(list(map(int,input().split())))
idx_que = deque(list(range(n)))
cnt = 0
while que:
if que[0] == max(que):
cnt += 1
que.popleft()
if idx_que.popleft() == x:
print(cnt)
else:
que.append(que.popleft())
idx_que.append(idx_que.popleft())
# popleft() queue 만의 방법
# list(range(n)) 0 부터 n-1 까지 리스트 생성
# while queue: 방법 if와 else로 구분해 pop만 시킬 것인지, pop시킨 것을 다시 append할 것인지 구분
1978 소수 찾기
# 1000*1000 = 1,000,000 완탐해도 시간초과가 안된다.
# case1. 완전탐색 + 소수특징 사용
import math
n = int(input())
li = list(map(int,input().split()))
cnt = 0
for num in li:
# 자연수만 오니까 1을 노린 것
if num < 2:
continue
else:
answer = True
for idx in range(2,int(math.sqrt(num))+1):
if num % idx == 0:
answer = False
break
if answer:
cnt +=1
print(cnt)
# case2. 에라토스테네스의 체
import math
n = int(input())
li = list(map(int,input().split()))
# 소수가 아니면 1 표시 / 0과1은 소수가 아님
d = [0] * 1001
d[0] = d[1] = 1
cnt = 0
# 1부터 1000까지 확인
for num in range(2,1001):
# 소수가 아님을 확정하지 못했다면
if d[num] == 0:
# 확인하기
for i in range(2,int(math.sqrt(num))+1):
# 소수가 아니라면
if num % i == 0:
# 배수는 다 소수가 아님을 처리
j = 1
while num*j <=1000:
d[num*j] = 1
j+=1
# 소수 카운트
for i in li:
if d[i] == 0:
cnt +=1
print(cnt)
# case2. 에라토스테네스의 체
import math
n = int(input())
li = list(map(int,input().split()))
# 소수가 아니면 1 표시 / 0과1은 소수가 아님
d = [0] * 1001
d[0] = d[1] = 1
cnt = 0
for i in range(2,int(math.sqrt(1000))+1):
if d[i] == 0:
# i는 제외하고 그 배수부터 읽음 처리
j = 2
while i*j <=1000:
d[i*j] = 1
j+=1
# 소수 카운트
for i in li:
if d[i] == 0:
cnt +=1
print(cnt)
2108 통계학
# sys.stdin.readline() = input()
# round(숫자,자리수) 반올림
# from collections import Counter
# cnt = sorted(cnt.items(),key=lambda x:(-x[1]:x[0]))
import sys
from collections import Counter
n = int(sys.stdin.readline())
s = []
for i in range(n):
s.append(int(sys.stdin.readline()))
s.sort()
print(round(sum(s)/n))
print(s[n//2])
c = Counter(s).most_common()
if len(s) > 1:
if c[0][1] == c[1][1]:
print(c[1][0])
else:
print(c[0][0])
else:
print(c[0][0])
print(s[-1] - s[0])
# Counter 클래스: 카운터객체, dic형태 가장 카운트부터 순서대로 배치가 됨
from collections import Counter
a = 'aabbbcccc'
print(Counter(a))
# Counter({'c': 4, 'b': 3, 'a': 2})
# most_common 메서드: 배열 리턴
Counter('hello world').most_common()
# [('l', 3), ('o', 2), ('h', 1), ('e', 1), (' ', 1), ('w', 1), ('r', 1), ('d', 1)]
cnt = Counter(data)
cnt = sorted(cnt.items(), key=lambda x: (-x[1],x[0])) # -붙이면 내림차순
# 내 풀이
import sys
from collections import Counter
n = int(sys.stdin.readline())
s = []
for _ in range(n):
s.append(int(sys.stdin.readline()))
# 산술평균
print(round(sum(s)/n))
# 중앙값
s.sort()
print(s[n//2])
# 최빈값
cnt = Counter(s)
cnt= sorted(cnt.items(), key=lambda x:(-x[1],x[0]))
# 최빈값이 두 개 이상이라면
if len(s) >1:
if cnt[0][1] == cnt[1][1]:
print(cnt[1][0])
else:
print(cnt[0][0])
else:
print(cnt[0][0])
#스코프
print(s[-1]-s[0])
2164 카드2
from collections import deque
n = int(input())
cards = deque([x for x in range(1,n+1)])
while len(cards) > 1:
cards.popleft()
cards.append(cards.popleft())
print(cards[0])
2292 벌집
# 코딩을 규격을 맞춰서 하려고 하니, 경직되게 짠다.
# 문제에 맞춰서 유동적으로 짜는 게 가장 중요하다.
# 상황에 맞춰서 상황에 맞는 코드를 작성하되, 규격의 코딩의 스킬을 이용하자.........
n=int(input())
num = 1 #벌집 번호
count = 1
while n>num:
num += 6*count
count +=1
print(count)
2609 최대공약수와 최소공배수
# GCD * LCM = GCD*GCD*A*B(A,B는 서로소) = a*b
# a*b//gcd(a,b) = lcm
X,Y=map(int,input().split())
x,y = X,Y
# 최대공약수 구하는 호제법
while y!=0:
x,y = y,x%y
print(x)
print(X*Y//x)
2775 부녀회장이 될테야
# 0 1 6 21
# 0 1 5 15 35 70
# 0 1 4 10 20 35 56
# 0 1 3 6 10 15 21 28 36 45 55 66 78
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13
t = int(input())
for i in range(t):
k = int(input())
n = int(input())
now_li = [1,2,3,4,5,6,7,8,9,10,11,12,13,14]
# 층
for p in range(k):
next_li =[]
for q in range(1,15):
next_li.append(sum(now_li[0:q]))
now_li = next_li
answer = now_li[n-1]
print(answer)
'''
다른 풀이(내 풀이와 차이점, 내 풀이는 인덱싱에 초점)
1) 최소 연산: 특정 호수를 알기 위해선, 특정호수까지만 계산하면 된다. 나는 전체 호수를 계산하고 그 전층의 결과를 리턴했따.
2) 유의미한 부분 코딩: 인덱스 교환 방식은 도중 오류나는 것을 직감하여 리스트를 교체하는 방법을 선택했다.
하지만 0번인덱스는 항상 1인 것을 생각해봤을 때, 1번부터 교환하면 문제가 되는 것이 아니였다.
3) f0 = [x for x in range(1,10)] 이런식의 리스트 초기화도 가능하다.
'''
t = int(input())
for _ in range(t):
floor = int(input()) # 층
num = int(input()) # 호
f0 = [x for x in range(1, num+1)] # 0층 리스트 f0 = [x for x in range(i,num+1)]
for k in range(floor): # 층 수 만큼 반복
for i in range(1, num): # 1 ~ n-1까지 (인덱스로 사용)
f0[i] += f0[i-1] # 층별 각 호실의 사람 수를 변경 f0[i] +=f0[i-1]
print(f0[-1]) # 가장 마지막 수 출력
2805 나무 자르기
# 나의 풀이
import sys
n,m = map(int,sys.stdin.readline().split())
li = list(map(int,sys.stdin.readline().split()))
li.sort()
#이진탐색으로 절단기의 높이를 설정하기
start = 0
end = max(li)
while start <= end:
mid = (start + end) // 2
sum = 0
for i in li:
if i - mid > 0:
sum += i-mid
# 필요량 만큼 딱 얻었을 경우
if sum == m:
answer = mid
break
# 필요량 만큼 더 얻었을 경우
elif sum > m:
start = mid + 1
answer = mid
# 필요량 보다 적게 얻을 경우
else:
end = mid - 1
print(answer)
# 다른 이의 풀이
from sys import stdin
from collections import Counter
def BS_tree(data,M):
start, end = 0, max(data)
result = 0
while start<= end:
total = 0
mid = (start+end)//2
for x,num in data.items():
if x > mid:
total += (x-mid)*num #해당 값이 등장한 개수만큼 곱한다
if total < M:
end = mid -1
else:
result = mid
start = mid + 1
return result
_, M = map(int, stdin.readline().split())
data = Counter(map(int, stdin.readline().split()))
print(BS_tree(data,M))
# 복습: 시간초과가 안나네? 3036 ms
from sys import stdin
def BS_Tree(li,m):
start,end = 0,max(li)
answer = 0
while start <= end:
mid = (start+end) //2
result = 0
for item in li:
if item > mid:
result+=item-mid
if result >= m:
start = mid + 1
answer = mid
else:
end = mid - 1
return answer
_,m = map(int,stdin.readline().split())
li = list(map(int,stdin.readline().split()))
print(BS_Tree(li,m))
# 복습: 카운터함수를 쓰니 시간이 급격히 줄어들었다 456 ms
from sys import stdin
from collections import Counter
def BS_Tree(data,m):
start,end = 0,max(data)
answer = 0
while start <= end:
mid = (start+end) //2
result = 0
for item, num in data.items():
if item > mid:
result+=(item-mid) * num
if result >= m:
start = mid + 1
answer = mid
else:
end = mid - 1
return answer
_,m = map(int,stdin.readline().split())
data = Counter(map(int,stdin.readline().split()))
print(BS_Tree(data,m))
2839 설탕 배달
n = int(input())
answer = 0
while n>0:
if n < 3:
answer = -1
break
else:
if n%5==0 and n>=5:
answer += 1
n -= 5
else:
answer+=1
n -=3
print(answer)
# 다른 풀이
# 배수가 계산에 획기적이다.
sugar = int(input())
bag = 0
while sugar >= 0 :
if sugar % 5 == 0 : # 5의 배수이면
bag += (sugar // 5) # 5로 나눈 몫을 구해야 정수가 됨
print(bag)
break
sugar -= 3
bag += 1 # 5의 배수가 될 때까지 설탕-3, 봉지+1
else :
print(-1)
4949 균형잡힌 세상
from sys import stdin
s = list(stdin.readline())
while s[0] !='.':
pa = 0 # 소괄호
br = 0 # 대괄호
stack = [] # 짝 맞는지 확인
for item in s:
if item =='(':
stack.append(')')
elif item =='[':
stack.append(']')
if item =='(':
pa += 1
elif item ==')':
pa -=1
elif item =='[':
br += 1
elif item ==']':
br -=1
# 괄호가 닫힐 경우
if pa < 0 or br < 0:
break
# 괄호가 엇갈릴 경우
if item ==')' or item ==']':
if stack.pop() != item:
break
# 괄호가 짝이 맞지 않을 경우
if pa ==0 and br==0:
print("yes")
else:
print("no")
s = list(stdin.readline())
9012 괄호
# 한 결과물 당 프린트 할 때 분기점을 생각하자
# if stack안의 if문의 else를 빼먹어서 print("NO")가 되지 않았음
for _ in range(int(input())):
s = list(input())
stack = ['flag']
for item in s:
if item =='(':
stack.append(item)
elif item ==')':
temp = stack.pop()
if temp =='flag':
break
if stack:
if stack.pop() =='flag':
print("YES")
else:
print("NO")
else:
print("NO")
10250 ACM 호텔
t = int(input())
for i in range(t):
h,w,n = map(int,input().split())
num = n//h+1
floor = n%h
if n % h ==0:
num=n//h
floor = h
print(f'{floor*100+num}')
'''
규칙성으로 봤을 때
층수는 n이 증가함에 따라 "주기"를 갖고 있고
호수는 n이 증가함에 따라 "늘어나는" 경향이 있다.
주기를 갖는 것은 %로 나머지 값을 보면 되고
늘어나는 것은 //로 몫을 보면 된다.
추가로 반례가 있다고, 로직을 포기 하는 게 아니라, 예외가 발생시 예외 패턴을 파악해 처리만 해주면 아주 개꿀딱이다.
보너스로 f'{}'(굳이표현안해됨) 과 층호수 표현법 복습한다.
'''
10814 나이순 정렬
n = int(input())
li =[]
for idx in range(n):
age,name = input().split()
li.append((int(age),name,idx))
li.sort(key=lambda x:(x[0],x[2]))
for info in li:
print(info[0], info[1])
# 나이와 순서 두개를 비교하는 것이다.
# 하지만 애초에 리스트가 입력받은 순 으로 저장됐으니 lambda x:x[2]는 굳이 필요 없겠군
10989 수 정렬하기 3
# 변수를 저장할 수 있는 메모리가 8mb로 제한되어있고, 입력개수는 천만개이다.
# 이 수들을 리스트에 하나씩 배열하면 메모리가 초과된다.
# 따라서 수는 10000보다 작은 자연수라는 점을 이용하여 문제를 푼다.
from sys import stdin
input = stdin.readline
n = int(input())
li = [0] * 10001
for _ in range(n):
li[int(input())] += 1
for i in range(1,10001):
if li[i] !=0:
for _ in range(li[i]):
print(i)
11866 요세푸스 문제 0
n,k = map(int,input().split())
li = list(range(1,n+1))
result = ['<']
index = 0
while li:
for _ in range(k-1):
if index == len(li)-1:
index = 0
else:
index += 1
result.append(li.pop(index))
result.append(',')
result.append(' ')
if index == len(li):
index = 0
result.pop()
result.pop()
result.append('>')
for x in result:
print(x, end='')
18111 마인크래프트
# 문제 성찰
"""
알고리즘, '완전탐색'이 필요한 문제였다.
쉬운 문제는 풀이대로 따라가다보면 자연스럽게 컴퓨팅적사고가 됐다.
하지만 이 문제는 풀이를 위해 컴퓨팅적 사고를 떠올려야 해서 막혔던 것 같다.
최적의 답을 위해 최적의 솔루션을 찾기보다 완전탐색으로 최적의 답을 찾는 문제다.
"""
# 새로 안 사실
"""
1.
Python, PyPy 모두 추가시간이 주어지지 않는다.
따라서 도중에 검사하기보다 모든 원소를 돌고나서 체크를 하는것이 낫다.
2.
d = [map(int, input().split())for _ in range(n)]
VS
d = []
for _ in range(n):
d += map(int, input().split())
첫번째 방법은 map객체가 리스트안에 그대로 들어가서 3개의 원소고
두번째 방법은 숫자가 차곡차곡 들어 sum(d)가 가능했다.
"""
# 실수
"""
d를 카운터로 바꾸고 합을 하니 ,중복되는 숫자가 다 없어져 적은 숫자가 나왔다.
여러 IDE를 쓰다보니, 코드 수정한 것을 제대로 반영하지 못했다.
"""
from sys import stdin
from collections import Counter
input = stdin.readline
n,m,b = map(int, input().split())
d = []
for _ in range(n):
d += map(int, input().split())
area, sum_block = n*m, sum(d)+b
d = Counter(d)
ans_time = 2e9
ans_height = 0
# 완전탐색으로 목표 높이를 고정시킨 후 시간 계산
for height in range(257):
# 갖고 있는 블록으로 땅을 평탕하게 할 수 있는지
if area * height <= sum_block:
now_time = 0
for key in d:
# 땅의 높이가 목표치보다 낮다면
if key < height :
now_time += (height-key) * d[key]
# 땅이 목표치 보다 높다면 = 땅을 파야함 = 2초
else:
now_time += (key-height) * d[key] * 2
if now_time <= ans_time:
ans_time = now_time
ans_height = height
print(ans_time, ans_height)
"""
# 예전 생각
배열의 모든 요소가 같게 하려면
모든 요소의 평균을 향해 더하거나 빼기를 통해?
더하는 것이 시간이 적기 때문에 더하는 것이 우선이 되어야함
평균값 반올림 정수를 향해?
"""