처음에 문제 이해를 잘못했었는데, 차분히 잘 생각해보니까 어느정도 구조가 눈에 보이기 시작했다.

 

즉, 주어진 "N 이하의 예쁜 수들로" N을 어떻게 만들 수 있을까? 라는 문제가 되겠다.

import math
N, K = map(int,input().split())

pretty_number = []
for i in range (1, N + 1):
    str_i = str(i)
    n = len(str_i)
    summary = 0
    for j in range (n):
        summary += int(str_i[j])
    if i % summary == 0:
        pretty_number.append(i)

dp = [0 for _ in range (0, N + 1)]

for i in range (0, len(pretty_number)):
    dp[pretty_number[i]] += 1
    for j in range (pretty_number[i] + 1, N + 1):
        dp[j] += dp[j - pretty_number[i]]
print(dp[-1] % K)

 

방식 자체는 굉장히 냅색 문제와 유사하게 되겠습니다.

 

굉장히 그리디하게 풀면 될 것 같은 느낌 (경우의 수를 구하는 경우에서는 특히 브루트포스로 구해도 될 것 같다)

 

답안 코드는 이하와 같다.

import sys 
from collections import defaultdict
input = sys.stdin.readline

N = int(input())
dict = {}
num = {}
for i in range (0,10):
    dict[i] = str(i)
    num[str(i)] = i
for i in range (0,26):
    dict[i + 10] = chr(i + 65)
    num[chr(i + 65)] = i + 10

summary = [0 for _ in range (0,36)]
#여기까지 기본 세팅
for _ in range (0,N):
    string =  input().rstrip()
    t = len(string)
    for i in range (0,t):
        summary[num[string[i]]] += (36 ** (t - i - 1))

K = int(input())

answer = 0

maximize = []
for i in range (0,36):
    maximize.append([dict[i], (35 - i) * summary[i]])

maximize.sort(key = lambda x: -x[1])


for i in range (0,K):
    answer += 35 * summary[num[maximize[i][0]]]

for i in range (K,36):
    answer += num[maximize[i][0]] * summary[num[maximize[i][0]]]


answer_string = []
while answer != 0:
    answer_string.append(dict[answer % 36])
    answer //= 36
    
answer_string = answer_string[::-1]
if answer_string != []:
    print("".join(s for s in  answer_string))
else:
    print("0")

 

(문제 사진이 안보인다... 어째서지)

 

 

문제 해결에 있어 주안점은 2가지가 되겠다.

 

1. 삼각형을 어떠한 방식으로 분할할 것인가? -> 정렬에 대한 이해 필요 / 회전체를 어떻게 분할 할 것인가?

 

2. 부피 공식의 구현

 

 

1.  x축에 대해서 회전을 시킬 경우, x축의 값에 따른 정렬

y축에 대해서 회전을 시킬 경우에는, y축의 값에 따른 정렬이 필요하겠다. 

정렬된 순서대로 부피를 구해주면 되겠다.

 

즉, (첫번째 - 두번째를 이은 직선으로 회전시켰을때) + (두번째 - 세번째를 이은 직선으로 회전시켰을 때) - (세번째 - 첫번째를 이은 직선으로 회전시켰을 때) 

 

2. 부피 공식의 구현에 있어서는 케이스를 조금 나눌 필요가 있다.

x좌표 혹은 y좌표가 같은지 확인할 필요가 있다. (두점이 주어졌을 때 직선의 방정식을 세워보게 되면, 두 점의 x좌표 혹은 y좌표가 같은 경우에는 직선의 방정식에서의 분모가 0이 되는 경우가 발생할 수 있으므로, ZeroDivisor Error가 나올 수 있겠다.)

이때는 그냥 깡구현으로 하면 되겠다. (사실 정적분이니까..)

 

해답은 다음과 같겠다.

import sys
import copy
import math
input = sys.stdin.readline

x1,y1,x2,y2,x3,y3 = map(int,input().split())
pts = [[x1,y1],[x2,y2],[x3,y3]]

pts.sort(key = lambda x: x[0])
sort_x_pts = copy.deepcopy(pts)
#x좌표 기준으로 정렬

pts.sort(key = lambda x:x[1])
sort_y_pts = copy.deepcopy(pts)
#y좌표 기준으로 정렬

def partial_vol(pt1,pt2):
    x1,y1 = pt1[0], pt1[1]
    x2,y2 = pt2[0], pt2[1]

    axis_x_vol, axis_y_vol = 0,0
    if x1 == x2:
        #x축 좌표는 동일한 경우이므로, x축 기준으로 회전했을때는 0
        x = x1
        axis_y_vol = math.fabs(math.pi * (x ** 2) * (y2 - y1))
    elif y1 == y2:
        #y축 좌표는 동일한 경우이므로, y축 기준으로 회전했을때는 0
        y = y1
        axis_x_vol = math.fabs(math.pi * (y ** 2) * (x2 - x1))
    else:
        a = (y2 - y1) / (x2 - x1)
        b = (x2 * y1 - x1 * y2) / (x2 - x1)
        c = (x2 - x1) / (y2 - y1)
        d = (y2 * x1 - x2 * y1) / (y2 - y1)

        axis_x_vol = math.fabs((x2 ** 3 - x1 ** 3) * (a ** 2 / 3) + (x2 ** 2 - x1 ** 2) * (a * b) + (x2 - x1) * b ** 2) * math.pi
        axis_y_vol = math.fabs((y2 ** 3 - y1 ** 3) * (c ** 2 / 3) + (y2 ** 2 - y1 ** 2) * (c * d) + (y2 - y1) * d ** 2) * math.pi
    return axis_x_vol, axis_y_vol

answer_x = math.fabs(partial_vol(sort_x_pts[0], sort_x_pts[1])[0] + partial_vol(sort_x_pts[1], sort_x_pts[2])[0] - partial_vol(sort_x_pts[2], sort_x_pts[0])[0])
answer_y = math.fabs(partial_vol(sort_y_pts[0], sort_y_pts[1])[1] + partial_vol(sort_y_pts[1], sort_y_pts[2])[1] - partial_vol(sort_y_pts[2], sort_y_pts[0])[1])

print(answer_x, answer_y)

 

1부터 K까지 prime에 해당된 소수를 전부 곱했을 때, 해당 소수(prime)의 지수를 묻는 것과 동일하게 볼 수 있겠다.

이하는 코드가 되겠다.

 

import math
import sys
from collections import defaultdict
sys.setrecursionlimit(10 ** 6)
input = sys.stdin.readline

N = int(input())
prime = list(map(int,input().split())) #prime의 길이가 N
K = int(input())

answer = 0
for i in range (0,N):
    cnt = 0
    num = K
    while num > 1:
        cnt += (num // prime[i])
        num //= prime[i]
    answer += cnt
print(answer)

 

 

 

 

Well-known인 다익스트라 알고리즘. ...

 

처음에 실수로 가중치가 왕복으로 주어지는줄 알았는데, 그게 아니라 편도였던 것....

 

수정하니 바로 맞는 결과가 나왔다.

import sys
import heapq
input = sys.stdin.readline
N = int(input())
M = int(input())
gp = [[] for _ in range (0,N+1)]
for _ in range (0,M):
    a,b,cost = map(int,input().split())
    gp[a].append((b,cost))
start, end = map(int,input().split())
INF = int(1e9)
dist = [INF for _ in range (0,N+1)]
q = []
dist[start] = 0
heapq.heappush(q, (dist[start], start))
while q:
    distance, node = heapq.heappop(q)
    if dist[node] < distance:
        continue
    for next, next_dist in gp[node]:
        d = distance + next_dist
        if d < dist[next]:
            dist[next] = d
            heapq.heappush(q, (dist[next], next))
print(dist[end])

 

문제 기준에 따라서 열심히 계산해주면 될 것 같다.

학생의 번호가 1~100 / 추천 횟수가 1000회 이하이므로 100 x 1000을 해도 연산에 있어 어려움은 없을 것 같다.

 

답안 코드는 다음과 같다.

import sys
from collections import defaultdict
input = sys.stdin.readline
N = int(input()) #사진틀의 개수
m = int(input())
rcd = list(map(int,input().split()))
candidate = defaultdict(int)
date = defaultdict(int) 
cnt = 0 #사진틀의 현재 갯수
for i in range (0,m):
    #사진첩에 걸린 후보수가 N에 도달했는지 확인
    if len(list(candidate.keys())) < N:
        candidate[rcd[i]] += 1
        if date[rcd[i]] == 0:
            date[rcd[i]] = i + 1 #시점 등록     
    else: #사진첩에 걸린 후보수가 N인 경우            
        if candidate[rcd[i]] == 0:#날짜 초기화도 해야함
            number = list(candidate.keys())
            removing = [] #없앨 후보자
            min_vote = int(1e9)
            for num in number:
                if candidate[num] != 0:
                    min_vote = min(min_vote, candidate[num])
            for num in number:
                if candidate[num] == min_vote:
                    removing.append((num, date[num]))
            removing.sort(key = lambda x : x[1])
            del_candidate, _ = removing[0][0], removing[0][1]
            candidate[del_candidate] = 0
            candidate[rcd[i]] += 1 
            date[del_candidate] = 0
            date[rcd[i]] = i + 1
        else:
            candidate[rcd[i]] += 1
            
number = list(candidate.keys())
answer = []
for num in number:
    if candidate[num] != 0:
        answer.append(num)
answer.sort()
print(*answer)

 

 

 

N, T, A라는 숫자가 주어지고, A와 T는 각각 현재 득표수를 나타내는 상황이며  N은 총 표수를 나타낸다.

이때 이 선거의 결과 여부를 판단하는 문제가 되겠다.

남아있는 표수를 구한 뒤, 케이스를 나눠 계산해주면 되겠다.

import sys
input = sys.stdin.readline

n,t,a = map(int,input().split())
remain = n - t - a
if t <= a:
    if t + remain < a:
        print("Yes")
    else:
        print("No")
elif a <= t :
    if a + remain < t:
        print("Yes")
    else:
        print("No")

 

 

 

 

주어진 문자열을 규칙에 맞게 출력해주면 되겠다.

즉, 아래에서부터 위로 읽어주는건데 (f->d->a... 순), 마지막에 딸려있는 공백은 읽지 않고,

중간에 껴있는 공백은 *를 넣어주면 되겠고, 해당 코드는 아래와 같이 나오겠다.

import sys
input = sys.stdin.readline

N = int(input())
max_length = -1
word = []
for _ in range (0,N):
    s = input().rstrip()
    word.append(s)
    max_length = max(max_length, len(s))
new_word = []
for i in range (0,N):
    new_s = word[i] + (max_length - len(word[i])) * "*"
    new_word.append(new_s)

answer = []

for i in range (0,max_length):
    word = ""
    cnt = 0
    for j in range (N-1,-1,-1):
        if new_word[j][i] != "*":
            word += cnt * "*"
            word += new_word[j][i]
            cnt = 0
        else:
            cnt += 1
    answer.append(word)
    
for ans in answer:
    print(ans)

 

 

 

 

 

 

 

주어진 쿼리에 따라서 명령어를 수행하면 되겠다.

 

1은 볼을 넣고, 

2는 볼을 빼고, (반드시 있다는 것이 보장)

3은 현재 숫자가 쓰여있는 볼의 종류 갯수 출력

 

딕셔너리를 사용하면 더욱 간편하게 풀 수 있는 것 같다. (시간복잡도도 굉장히 좋기때문)

 

import sys
from collections import defaultdict
input = sys.stdin.readline


Q = int(input())
d = defaultdict(int)
cnt = 0
def f(cmd):
    global d
    global cnt
    if len(cmd) == 1: #케이스 3의 경우
        print(cnt)  #cnt가 갯수를 뜻하겠다
    elif len(cmd) == 2:
        if cmd[0] == 1: #케이스 1의 경우
            d[cmd[1]] += 1
            if d[cmd[1]] == 1:
                cnt += 1
        elif cmd[0] == 2: #케이스 2의 경우
            d[cmd[1]] -= 1
            if d[cmd[1]] == 0:
                cnt -= 1
                
for _ in range (0,Q):
    cmd = list(map(int,input().split()))
    f(cmd)

 

 

3차원 prefix 문제가 되겠다.

3차원의 직육면체를 분할해서 생각해보면 좋을 것 같다.

 

import sys
from collections import defaultdict
input = sys.stdin.readline

N = int(input())
num = [[[0 for _ in range (0,N+1)] for _ in range (0,N+1)] for _ in range (0,N+1)]
for i in range (0,N):
    for j in range (0,N):
        a = list(map(int,input().split()))
        for k in range (0,N):
            num[i+1][j+1][k+1] = a[k]
prefix = [[[0 for _ in range (0,N+1)] for _ in range (0,N+1)] for _ in range (0,N+1)]
for i in range (1,N+1):
    for j in range (1, N+1):
        for k in range (1,N+1):
            prefix[i][j][k] = prefix[i][j][k-1] + prefix[i][j-1][k] + prefix[i-1][j][k] - prefix[i-1][j-1][k] - prefix[i-1][j][k-1] - prefix[i][j-1][k-1] + prefix[i-1][j-1][k-1] +num[i][j][k]

Q = int(input())
for _ in range (0,Q):
    l_x,r_x,l_y,r_y,l_z,r_z = map(int,input().split())
    l_x,l_y,l_z = l_x-1, l_y-1, l_z-1
    answer = prefix[r_x][r_y][r_z] - prefix[l_x][r_y][r_z] - prefix[r_x][l_y][r_z] - prefix[r_x][r_y][l_z] + prefix[r_x][l_y][l_z]  + prefix[l_x][r_y][l_z]  + prefix[l_x][l_y][r_z]  - prefix[l_x][l_y][l_z]
    print(answer)

 

E,F는 수학쪽에 가까운 문제 같았는데 못 풀어서 상당히 아쉬웠다.

 

힘내서 풀어봐야겠다.

 

 

https://www.acmicpc.net/problem/17404

 

 

 

해답코드는 아래와 같다.

N = int(input())
cost = []
for _ in range (0,N):
    a = list(map(int,input().split()))
    cost.append(a)

def f(N, cost):
    if N == 2:
        return min(cost[0][0] + cost[1][1], cost[0][0] + cost[1][2], cost[0][1] + cost[1][2], cost[0][1] + cost[1][0], cost[0][2] + cost[1][0], cost[0][2] + cost[1][1])
    else:
        #dpi_j는 시작이 i고 마지막이 j색인 것
        dp1_2, dp1_3 = [cost[0][0], cost[0][0] + cost[1][1]], [cost[0][0], cost[0][0] + cost[1][2]]
        dp2_1, dp2_3 = [cost[0][1], cost[0][1] + cost[1][0]], [cost[0][1], cost[0][1] + cost[1][2]]
        dp3_1, dp3_2 = [cost[0][2], cost[0][2] + cost[1][0]], [cost[0][2], cost[0][2] + cost[1][1]]
        dp1_1, dp2_2, dp3_3 = [], [], []
        for i in range (3, N + 1):
            x1_2, x1_3 = dp1_2[-1], dp1_3[-1]
            x2_1, x2_3 = dp2_1[-1], dp2_3[-1]
            x3_1, x3_2 = dp3_1[-1], dp3_2[-1]

            if dp1_1 == []:
                dp1_1.append(min(x1_2, x1_3) + cost[i - 1][0])
                dp2_2.append(min(x2_1, x2_3) + cost[i - 1][1])
                dp3_3.append(min(x3_1, x3_2) + cost[i - 1][2])

                dp1_2.append(x1_3 + cost[i-1][1])
                dp1_3.append(x1_2 + cost[i-1][2])
                dp2_1.append(x2_3 + cost[i-1][0])
                dp2_3.append(x2_1 + cost[i-1][2])
                dp3_1.append(x3_2 + cost[i-1][0])
                dp3_2.append(x3_1 + cost[i-1][1])
            else:
                dp1_2.append(min(dp1_1[-1], x1_3) + cost[i - 1][1])
                dp1_3.append(min(dp1_1[-1], x1_2) + cost[i - 1][2])
                dp2_1.append(min(dp2_2[-1], x2_3) + cost[i - 1][0])
                dp2_3.append(min(dp2_2[-1], x2_1) + cost[i - 1][2])
                dp3_1.append(min(dp3_3[-1], x3_2) + cost[i - 1][0])
                dp3_2.append(min(dp3_3[-1], x3_1) + cost[i - 1][1])

                dp1_1.append(min(x1_2, x1_3) + cost[i - 1][0])
                dp2_2.append(min(x2_1, x2_3) + cost[i - 1][1])
                dp3_3.append(min(x3_1, x3_2) + cost[i - 1][2])

        return min(dp1_2[-1], dp1_3[-1], dp2_1[-1], dp2_3[-1], dp3_1[-1], dp3_2[-1])


print(f(N, cost))

 

 

Dp 문제인데, 이러한 점화식 계열로 나오는 문제들의 경우에는 케이스를 잘 나누어 주는 것이 키포인트 같다.

array의 네이밍에서부터, 처음 시작 색 - 마지막 색을 정하는 것이 가능하다. (단 6가지에 불과하다.)

 

문제를 풀면서 3번째 예제에서 많이 막혔었는데, 이때 i_i로 나타내지는 array를 계산하지 않았던 것이 컸던 것 같다.

i_i인 array는 실제 문제의 답에서 나오지는 않지만, 징검다리 역할이라고 해야하나.

도중 관계에서 나오게 되겠다.

 

+ Recent posts