[백준 2981번][Python/파이썬] 검문

공학도 Lee·2023년 2월 9일
0

백준 문제 풀이

목록 보기
34/63
post-custom-banner

1. 문제


출처: 백준 2981번 검문

2. 풀이


숫자들이 너무 크기 때문에, 그대로 일일이 계산한다면 시간 초과가 발생할 수밖에 없다.

따라서, 유클리드 호제법을 적극 활용해야 한다.

유클리드 호제법

두 양의 정수 a,ba,b (a>b)(a > b)에 대하여 a=bq+ra=bq+r (0r<b)(0\leq r<b)이라 하면, a,ba,b의 최대공약수는 b,rb,r의 최대공약수와 같다. 즉,

gcd(a,b)=gcd(b,r)gcd(a,b) = gcd(b,r)

r=0r=0이라면 a,ba,b의 최대공약수는 bb가 된다.

그리고, 같은 나머지를 가지는 숫자를 구하는 것이므로, 주어진 숫자들의 차이로 리스트를 만들고 이들의 공약수를 구해도 된다.

A=GQ1+rA=GQ_1+r이고 B=GQ2+rB=GQ_2+r일 때, AB=G(Q1Q2)A-B = G(Q_1-Q_2) 이다.

모든 차이들에 대해서 최대공약수를 구하고 최대공약수의 약수들을 구해서 출력해 주면, 문제에서 요구하는 나머지가 모두 같게 되는 MM들을 구할 수 있다.

약수를 구하는 과정에서 시간 초과가 뜨지 않도록, 유의해 준다.

3. 소스코드


case = int(input())
number = []
for _ in range(case):
    number.append(int(input()))

#유클리드 호제법
def gcd(a,b):
    A = max([a,b])
    B = min([a,b])
    if A%B == 0:
        return B
    else:
        return gcd(B,A%B)

#숫자 차이들의 최대공약수를 구하자 
test = []
for l in range(len(number)-1):
    test.append(abs(number[l]-number[l+1]))
number = test

#단 하나의 최대공약수가 남을 때까지 반복
while len(number)!=1:
    number_edit = set()
    for i in range(len(number)-1):
        number_edit.add(gcd(number[i],number[i+1]))
    number = list(number_edit)

M = {number[0]}
for k in range(2,number[0]):
    if k > number[0]//k:
        break
    if number[0] % k ==0:
        M.add(k)
        M.add(number[0]//k)
M=list(M)
M.sort()
print(*M, sep=" ")

4. 그 외


오래간만에 정수론 문제를 푸니, 중학교 때 기억이 새록새록 났다.
숫자들이 커서 시간 초과가 나는 경우가 많아서, 다른 분들의 풀이를 참고해서 숫자를 줄여나가는 과정을 배울 수 있었다.

profile
이창민, Changmin Lee
post-custom-banner

0개의 댓글