728x90

 

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)
728x90

 

 

 

 

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])
728x90

 

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

학생의 번호가 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)

 

728x90

 

 

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는 수학쪽에 가까운 문제 같았는데 못 풀어서 상당히 아쉬웠다.

 

힘내서 풀어봐야겠다.

 

 

728x90

분리집합이라는 말을 들었을 때, Disjoint Set이라는 단어가 일단 생각이 났다.

 

아무리봐도 Intersection이 없는 집합들 이라고 생각할 수 있겠다.

 

사실 백준에서 문제 하나를 풀고 있었는데, 이거 태그가 분리집합이라서 ... 공부를 해야겠다고 생각하게 된듯.

 

즉, [1,2,3,4,5,6] 같은 집합이 주어져있을 때, 이들을 어떻게 묶을 것인지? 

 

어떻게 보면 Strongly Connected Component들이 구성되어있는가? 가 되겠다.

 

먼저 이러한 분리 집합을 생각함에 있어서 Union - Find라는 두개의 function을 통해서 정의된다.

 

첫번째로, Find (특정 원소가 어디에 소속되어있는지?)

 

def find(parent, x):
	if parent[x] != x:
    	return find(parent, parent[x])
    return x

 

이런 방식으로 재귀를 통해 x의 parent를 찾아가는 과정을 취한다.

 

다음으로는, 두개의 분리집합을 합치는 과정이 되고, Union이다.

def union(parent,a,b):
	a = find(parent, a)
    b = find(parent, b)
    if a < b:
    	parent[b] = a #작은쪽으로 맞추기 위해
    else:
    	parent[a] = b #작은쪽으로 맞추기 위해

 

이제 이러한 개념을 알아뒀으니 ,,,, 못풀었던 문제들을 해결하기 위해 떠나봐야겠다.

 

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

'스터디' 카테고리의 다른 글

4주차 스터디(23.12.01)-2  (1) 2023.12.01
4주차 스터디(23.12.01)  (1) 2023.11.30
3주차 스터디(23.11.24)  (0) 2023.11.30
2주차 스터디(23.11.16) - DFS, BFS  (0) 2023.11.11
1주차 스터디(23.11.09) - 완전 탐색 (Brute Force)  (0) 2023.11.07
728x90

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는 실제 문제의 답에서 나오지는 않지만, 징검다리 역할이라고 해야하나.

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

 

728x90

 

부분합 전통적인 문제입니다.

 

문제에서 S "이상" 이라는 것을 못보고 뻘짓하느라 오답을 마구마구 제출했네요 ,,,

 

코드는 이하와 같습니다.

 

prefix_sum의 i번째 원소를 num[i]까지의 합이라고 하면

num_i 부터 num_j까지의 합은 prefix_sum[j] - prefix_sum[i-1] 가 됩니다.

이를 활용하면 다음과 같습니다.

import sys
input = sys.stdin.readline

N,S = map(int,input().split())
num = list(map(int,input().split()))
prefix = [0]
for i in range (0,N):
    prefix.append(prefix[-1] + num[i])
    
answer = []
l,r = 0,1
while l < r and r != N+1:
    partial_sum = prefix[r] - prefix[l]
    if partial_sum >= S:
        answer.append(r-l)
        l += 1
    elif partial_sum < S:
        r += 1


answer.sort()

if len(answer) == 0:
    print(0)
else:
    print(answer[0])

 

 

 

 

 

'코딩' 카테고리의 다른 글

[ABC 366] AtCoder Beginner Contest 366 리뷰  (0) 2024.08.17
[BOJ, 백준] 17404 RGB 거리 2  (0) 2024.08.12
[BOJ, 백준] 8895 막대배치 Python  (0) 2024.08.05
[BOJ, 백준] 7869 두 원  (0) 2024.07.26
[BOJ, 백준] 1007 벡터매칭 Python  (0) 2024.07.26
728x90

 

조합론 문제를 덜 풀었길래 ... 조합론 문제를 찾다보니 이런 친구를 찾았습니다.

 

아이디어는 다음과 같습니다.

 

처음에 3차원 array를 만들어줍니다. (dp로서 문제를 해결하기 위해)

 

첫번째 인덱스는 막대의 갯수 / 두번째 인덱스는 왼쪽에서 봤을때의 개수 / 세번째 인덱스는 오른쪽에서 봤을때의 개수 입니다.

 

초기값 설정을 위해, dp[1][[1][1]은 1개가 되는 것으로 설정을 해둡니다.

이후 다음과 같이 생각할 수 있겠습니다.

 

dp[i][j][k]는 블럭이 i개, 왼쪽에서 봤을 때 j개 / 오른쪽에서 봤을 때 k개가 됩니다.

이때 블럭은 다음과 같이 나타낼 수 있습니다.

첫번째 오는 블럭의 높이를 h_1이라고 하고 두번째는 h_2 ... 마지막은 h_i 라고 합니다.

 

이때, 왼쪽에서 봤을 때 j개 라는 것은

h_1 = h_(l_1) < h_(l_2) < h_(l_3) < ... < h_(l_j) 

(단, 1 <= l_1 < l_2  <  .... < l_j <= i )

 

반대로, 오른쪽에서 봤을 때 k개 라는 것은

h_(r_k) > h_(r_(k-1)) >  .... > h_(r_2) > h_(r_1) = h_i

(단, 1 <= r_k < r_(k-1) < .... < r_1 <= i)

라는 뜻이 되겠습니다.

 

이 상황에서, 모든 블럭의 높이를 +1씩 해도 위의 2개의 부등식은 바뀌지 않을 것입니다.

예를 들어보면

 

주어진 블럭의 높이가 

2 4 3 1 이라면 i = 4, j = 2, k = 3입니다.

j = 2 : 2 < 4 (인덱스 (l_x에 해당하는 부분)는 1 <= 1 < 2 <= 4)

k = 3 : 4 > 3 > 1 (인덱스 (r_x에 해당하는 부분)는 1 <= 2 < 3 < 4 <= 4)

 

이제 다음 스텝을 생각한다면 모든 블럭의 높이를 1씩 올린다 했으므로 3 5 4 2가 되겠습니다.

이렇게 해도 변화는 없겠습니다.

 

이제 높이가 1인 블럭을 어디에 넣느냐? 가 중요해집니다.

 

1. 가장 왼쪽에 넣을 때

1 3 5 4 2 가 되면서

i = 5, j = 3, k = 3이 되겠습니다. (i, j가 1씩 늘어났습니다.)

 

2. 가장 오른쪽에 넣을 때

3 5 4 2 1이 되면서

i = 5, j = 2, k = 4가 되겠습니다. (j, k가 1씩 늘어났습니다.)

 

3. 그 외에 넣을 때

3 1 5 4 2 i = 5, j = 2, k = 3

3 5 1 4 2 i = 5, j = 2, k = 3

3 5 4 1 2 i = 5, j = 2, k = 3 (i만 1이 늘어났습니다.)

 

그렇다면 이러한 상황을 코드로 작성한다면 다음과 같이 되겠습니다.

import sys
input = sys.stdin.readline

T = int(input())
for _ in range (0,T):
    n,l,r = map(int,input().split())
    dp = [[[0 for _ in range (0,r+2)] for _ in range (0,l+2)] for _ in range (0,n+2)]
    dp[1][1][1]= 1
    for i in range (2, n+1):
        for j in range (1, l+1):
             for k in range (1, r+1):
                dp[i][j][k] += dp[i - 1][j - 1][k]
                dp[i][j][k] += dp[i - 1][j][k - 1]
                dp[i][j][k] += dp[i - 1][j][k] * (i - 2)

    print(dp[n][l][r])

 

'코딩' 카테고리의 다른 글

[BOJ, 백준] 17404 RGB 거리 2  (0) 2024.08.12
[BOJ, 백준] 1806 부분합 Python  (0) 2024.08.10
[BOJ, 백준] 7869 두 원  (0) 2024.07.26
[BOJ, 백준] 1007 벡터매칭 Python  (0) 2024.07.26
[BOJ, 백준] 1256 사전 Python  (0) 2024.07.26
728x90

 

 

 

중요한 것은 소수점 셋째자리까지 출력하는 것이겠다.

 

예를 들어, 0이라면 0.000으로 출력하는 것인데 이 부분에 대해서는 문자열로 출력해주기로 했다.

 

두 원의 위치 관계에 대해서는 중심 사이의 거리와 반지름을 활용하면 되겠다.

 

import math
x_1,y_1,r_1,x_2,y_2,r_2 = map(float,input().split())

#일반적으로 r1이 r2보다 더 길거나 같다고 가정하자.
if r_1 < r_2:
    new_x, new_y, new_r = x_1,y_1,r_1
    x_1,y_1,r_1 = x_2,y_2,r_2
    x_2,y_2,r_2 = new_x, new_y, new_r

d = math.sqrt((x_2 - x_1) ** 2 + (y_2 - y_1) ** 2)
r_sum = (r_1 + r_2) ** 2
r_diff = (r_1 - r_2) ** 2


#한점에서도 만나지도 않고 아예 외부에 존재하는 경우, 외부의 한점에서 만나는 경우
if r_sum <= d ** 2:
    answer = "0.000"
    print(answer)

#두 원중 작은쪽의 원이 내접, 포함하고 있는 경우
elif r_diff >= d ** 2:
    answer = math.pi * (r_2 ** 2)
    print(round(answer, 3))

#그 외의 경우
else:
    theta_1 = 2 * math.acos((r_1 ** 2 + d ** 2 - r_2 ** 2) / (2 * r_1 * d))
    theta_2 = 2 * math.acos((r_2 ** 2 + d ** 2 - r_1 ** 2) / (2 * r_2 * d))
    answer = (r_1 ** 2) * (theta_1 - math.sin(theta_1)) / 2 + (r_2 ** 2) * (theta_2 - math.sin(theta_2)) / 2
    print(round(answer, 3))

'코딩' 카테고리의 다른 글

[BOJ, 백준] 1806 부분합 Python  (0) 2024.08.10
[BOJ, 백준] 8895 막대배치 Python  (0) 2024.08.05
[BOJ, 백준] 1007 벡터매칭 Python  (0) 2024.07.26
[BOJ, 백준] 1256 사전 Python  (0) 2024.07.26
[BOJ, 백준] 13206 Professor KCM Python  (0) 2024.07.25
728x90

 

 

문제는 다음과 같다

 

해답 코드는 다음과 같이 나오겠다.

 

이 문제에서 중요하다고 느껴지는 것은, 포함된 벡터들의 "합"의 크기의 최솟값인 점이 되겠다.

주어진 좌표가 (x1,y1) , ... , (x_2n, y_2n) 이러한 형식으로 주어져있다면

initial point들의  좌표를 (nx_1, ny_1) , ... , (nx_n, ny_n)로 둘 수 있겠고

terminate point들의 좌표를 (mx_1,my_1), ..., (mx_n, my_n)으로 둘 수 있겠다.

 

이렇게 좌표를 나누는 것이 가능했을 때, 이곳의 벡터들의 합은 항상 고정되는 것을 알 수 있다. 

(nx_1, ny_1)이 (mx_1, my_1), ... , (mx_n, my_n) 중 하나로 매칭되어서 (mx_k1, my_k1)과 매칭 되었을 때  얻어지는 벡터는

(mx_k1 - nx_1 , my_k1 - ny_1)꼴이다.

같은 방식으로 (nx_2, ny_2)는 (mx_1, my_1), ...  (mx_(k1 -1), my_(k1 - 1)),  (mx_(k1 + 1), my_(k1 + 1))... , (mx_n, my_n) 중 하나로 매칭되어서 얻어지는 벡터는

(mx_k2 - nx_2, my_k2 - ny_2) 꼴이 되겠다.

반복해서 진행하면 전부 일대일로 매칭되겠고

결국 벡터 성분의 합은

(mx_1 + ... + mx_n - nx_1 - ... - nx_n, my_1 + ... + my_n -  ny_1 - ... - ny_n) 꼴로 일의적 (uniquely)하게 주어지는 것을 알 수 있겠다.

 

이 성질을 활용하면 알고리즘을 짜본다면 다음과 같이 얻어질 수 있겠다.

import sys
import math
from itertools import combinations

T = int(input())
for _ in range (0,T):
    num_pt = int(input())
    pts = []
    sum_x, sum_y = 0, 0
    for _ in range (0,num_pt):
        a,b = map(int,input().split())
        sum_x += a
        sum_y += b
        pts.append([a,b])
    initial = list(combinations(pts, num_pt // 2))
    answer = int(1e9)
    for init_pt in initial:
        init_pt = list(init_pt)
        ini_x, ini_y = 0, 0
        for pt in init_pt:
            ini_x += pt[0]
            ini_y += pt[1]
        ter_x, ter_y = sum_x - ini_x , sum_y - ini_y
        answer = min(answer, math.sqrt((ter_x - ini_x) ** 2 + (ter_y - ini_y) ** 2))
    print(answer)

'코딩' 카테고리의 다른 글

[BOJ, 백준] 8895 막대배치 Python  (0) 2024.08.05
[BOJ, 백준] 7869 두 원  (0) 2024.07.26
[BOJ, 백준] 1256 사전 Python  (0) 2024.07.26
[BOJ, 백준] 13206 Professor KCM Python  (0) 2024.07.25
[BOJ, 백준] 30025 K의 배수 Python  (0) 2024.07.24

+ Recent posts