알고리즘/Python

백준 알고리즘 2485번: 가로수 (Python)

두넌 2023. 6. 29.

문제 정보


 

 

2485번: 가로수

첫째 줄에는 이미 심어져 있는 가로수의 수를 나타내는 하나의 정수 N이 주어진다(3 ≤ N ≤ 100,000). 둘째 줄부터 N개의 줄에는 각 줄마다 심어져 있는 가로수의 위치가 양의 정수로 주어지며, 가

www.acmicpc.net

 

핵심


 

최대공약수 문제다! 라는 것을 빠르게 캐치하여야 함

일일히 최대공약수를 구하는것은 정말 비효율적이니, 유클리드 호제법을 통해서 구하는 것이 올바른 풀이이다

각 가로수의 간격들의 전체 최대공약수를 구하고 이 간격에서 비어있는 가로수의 개수를 찾아서 출력해주면 된다

 

 

풀이


from sys import stdin

N = int(stdin.readline())
tree = list(map(int, stdin.readlines()))

def GCD(a, b):
    r = a % b
    if r == 0:
        return b
    return GCD(b, r)

tmp = tree[1] - tree[0]
for i in range(1, N-1):
    tmp = GCD(max(tmp, tree[i+1] - tree[i]), min(tmp, tree[i+1] - tree[i]))
    if tmp == 1:
        break

print(((tree[-1] - tree[0]) // tmp + 1) - len(tree))

 

일단, 배열 tmp 에는 먼저 두번째 가로수와 첫번째 가로수의 간격 차이를 넣어놓고

그 다음 수들의 간격과 최대공약수 연산을 하고 tmp 에 다시 저장한다

이후에는 이전의 최대공약수와 다음 간격간의 최대공약수를 계속 구해나간다

 

만약 1이 되면, 어차피 이후 연산에서의 최대공약수는 1이기에 break 하고 결과를 출력한다

이 과정을 통해서 모든 간격들의 최대 공약수를 구할 수 있다

 

마지막 결과값 출력 부분의 수식의 의미는 다음과 같다

맨 마지막 가로수가 떨어진 위치에서 첫번째 가로수가 떨어진 위치를 빼면 맨 처음부터 맨 끝까지의 거리가 나온다

이는 범위를 구하는 것이다

여기서 tmp (가로수 간격의 최대공약수)를 나누어주면 간격에서 있을 수 있는 모든 가로수가 나오는데, 이 값은 처음 혹은 끝 지점을 포함하지 않는 값이기에 +1 을 해준다

 

그 후 가로수의 개수를 빼주면 심어야 할 가로수의 개수가 나오는 것이다

 

 

고찰


# https://www.acmicpc.net/source/62391055

from math import gcd #최대 공약수 찾는 함수

n, *n_list = map(int, open(0).read().split())

#두 지점 사이의 거리
len_n = [j-i for i,j in zip(n_list[:-1],n_list[1:])]

#모든 원소의 최대공약수 한번에 구할 수 있음
g = gcd(*len_n)

#가로수 개수 구하기: 두 나무 사이의 거리를 최대 공약수로 나누고 -1(이미 있으니까)
answer = sum([each//g-1 for each in len_n])
print(answer)

해당 풀이는 다른 분의 코드를 참고하였는데, 이분은 두 지점사이의 거리를 먼저 구하고,

math 라이브러리의 gcd 함수를 사용하여 전체 간격들의 최대공약수를 구하셨다

 

 

참고


 

GitHub - dduneon/CodingTestPy

Contribute to dduneon/CodingTestPy development by creating an account on GitHub.

github.com

댓글