Algorithm/Baekjoon
[백준] 수학_15650, 1037, 2981, 1789, 2407, 15663, 15657, 2824
밍츠
2022. 9. 1. 09:48
N과 M (2)
- 코드
n, m = map(int, input().split())
answer = []
def dfs(idx, temp):
if len(temp) == m:
answer.append(temp)
return
for i in range(idx, n):
dfs(i+1,temp+[i+1])
dfs(0, [])
for i in answer:
print(" ".join(str(s) for s in i))
- 풀이를 생각해낸 과정
- 재귀 함수를 이용하여 조합 구현
- n = 4, m=3이라고 할 때,
- step1) dfs(0,[]) → dfs(1,[1]) → dfs(2,[1,2]) → dfs(3, [1,2,3])
- step2) m값과 temp 의 길이가 같아지면 즉 원하는 개수 모두 뽑으면 해당 탐색 끝, dfs(2,[1,2]) 에서 dfs(4,[1,2,4]) 호출
- step3) dfs(2,[1,2]) 탐색 끝, dfs(1,[1])에서 dfs(1,[1,3]) 호출 후 해당 과정 반복
- step4) dfs(0,[])에서 dfs(2,[2]) 호출 후 해당 과정 반복
- point) temp의 길이와 m 값이 같다면 answer 리스트에 해당 리스트 값 추가
약수
- 코드
n = int(input())
temp = list(map(int,input().split()))
print(min(temp)*max(temp))
- 풀이를 생각해낸 과정
- 32비트 부호있는 정수 = int
- 약수의 곱은 대칭성을 띄기 때문에 입력 받은 진짜 약수에서 가장 작은 수와 가장 큰 수를 곱해서 계산한다.
- 시간복잡도 계산
- min, max - O(N)
검문
- 코드
import math
def Gcd(a,b):
if a < b:
a, b = b, a
while a > 0:
b, a = a, b%a
return b
n = int(input())
arr = [int(input()) for i in range(n)]
arr.sort()
new = [] # arr[i+1] - arr[i] 값 저장
result = [] # 최대공약수의 약수 값 저장
for i in range(len(arr)-1):
new.append(arr[i+1]-arr[i])
gcd = new[0]
for i in range(1,len(new)):
gcd = Gcd(new[i],gcd)
for i in range(2,int(math.sqrt(gcd))+1):
if gcd % i == 0:
result.append(i)
result.append(gcd//i)
result.append(gcd) #2부터 확인하여 1과 대응되는 자기 자신 추가
result = sorted(list(set(result))) # 중복 제거 ex) 4의 약수 1,2,4 면 2가 중복해서 들어간다.
print(" ".join(map(str,result))) # print(*result)
- 풀이를 생각해낸 과정
- 반복문을 돌면서 나누어지는지 확인하는 경우로 생각 → 시간 초과
- 수학 공식을 활용하여 풀기
- 즉,
- B - C = M ( b - c )
- 여기서 R을 제거하면
- B = M * b + R
- 시간복잡도 계산
- O(N)
수들의 합
- 코드
import math
n = int(input())
s = 0 # 1~k 의 합을 저장하는 변수
k = 1
while s <= n:
s += k
if s > n:
break
k += 1
print(k-1)
- 풀이를 생각해낸 과정
- 1부터 1씩 증가시키면서 n을 만들어가는 것이 최대 개수를 보장한다.
- 시간복잡도 계산
- O(n), O(루트N)
O(n)제곱근 시간 알고리즘(Square root algorithm)은 O(log n) 보다 느리지만, O(n)보다는 빠르다.
- 1~ n 까지의 합이 n*(n+1) / 2 이므로 while 문의 반복이 최대 2n의 제곱근 만큼 반복된다.
조합
- 코드
n,m = map(int,input().split())
dp = [0] * (n+1)
dp[0] = 1
dp[1] = 1
for i in range(2, n+1):
dp[i] = dp[i-1] * i
print(dp[n] // (dp[m] * dp[n-m]))
- 풀이를 생각해낸 과정
- 팩토리얼을 dp로 푸는 방법을 이용
- 재귀함수를 사용하면 중복 연산 발생
- 정수 형으로 바꿔서 출력했는데 오답 처리, 그대로 출력하는 것이 정답
- 팩토리얼을 dp로 푸는 방법을 이용
- 시간복잡도 계산
- O(N)
N과 M (9)
- 시간 초과
- 코드
n, m = map(int, input().split())
num = list(map(int,input().split()))
num.sort()
result = []
def choice(i, temp):
if len(temp) == m:
if temp not in result:
print(" ".join(map(str,temp)))
result.append(temp)
return
for j in range(n):
if j!= i:
choice(j,temp+[num[j]])
for i in range(len(num)):
choice(i,[num[i]])
- 풀이를 생각해낸 과정
- 중복 상관없이 담고 출력할 때 제외하기
- 담을 때 중복 고려해서 담기
- 시간복잡도 계산
N과 M (8)
- 코드
n, m = map(int, input().split())
arr = list(map(int,input().split()))
arr.sort()
def sequence(n, temp):
if len(temp) == m:
print(' '.join(map(str,temp)))
return
for i in range(n,len(arr)): #인덱스로 접근하여 중복 방지, n : 탐색 중인 인덱스
sequence(i,temp+[arr[i]])
sequence(0,[])
#(0,[]) -> (0,[1])
# -> (0,[1,1]) -> (0,[1,7]) -> (0,[1,8]) ->(0,[1,9])
# -> (1,[]) -> (1,[7])
# -> (1,[7,7]) -> (1,[7,8])
- 풀이를 생각해낸 과정
- 백트래킹, sequence 함수에서 자신부터 탐색을 시작하게 설정하여 자기 자신을 포함시키고 중복 수열을 방지하도록 구현
- 시간복잡도 계산
- O(N)
최대공약수
- 코드
#14:21 ~ 14:37
n = int(input())
a = list(map(int,input().split()))
m = int(input())
b = list(map(int,input().split()))
def mul(temp):
k = 1
for i in temp:
k*=i
return k
def gcd(a,b):
if a<b:
a, b = b, a
while a>0:
b, a = a, b%a
return b
result = str(gcd(mul(a),mul(b)))
if len(result) >9:
print(result[-9:])
else:
print(result)
- 풀이를 생각해낸 과정
- 곱셈 과정 함수화, 유클리드 호제법 함수화
- 최대 공약수 결과 문자열로 바꿔 9자리가 넘어가는 경우 슬라이싱
- 시간복잡도 계산
- O(N)