BOJ 단계별 (9) : 약수, 배수와 소수

Tarte·2025년 5월 14일

코딩테스트

목록 보기
8/28

5086

내 풀이

while True:
    a, b = map(int, input().split())
    if a == 0 and b == 0:
        break

    if a % b == 0:
        print("multiple")
    elif b % a == 0:
        print("factor")
    else:
        print("neither")

2501

내 풀이

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

k_lst = []

for i in range (1, N+1): #N의 약수 리스트 
	
	if N % i == 0 :
		k_lst.append(i)

length = len(k_lst)

if  length < K :
	print(0)
else :
	print(k_lst[K-1])

정리

문법

1. for 반복문 range()
for i in range(1, N+1) # 1부터 N까지 반복
- range(a, b) : a 이상 b 미만 숫자 생성

2. list 값 추가: .append()

3. list에서 K번째 원소 가져올 때: K - 1
- 0번 인덱스부터 시작하기 때문에

9506

내 풀이

#테스트 케이스 입력 받는 부분
#while true로 때리고 입력값이 -1일 때 break로 종료하면 되지 않나?


while True:

	n = int(input())

	if n == -1:
		break

#완전수를 판별하는 부분

	n_lst = []

	for i in range (1, n): #약수 리스트 만들기(1 이상 n 미만이라 자연스럽게 n 제외됨)
		
		if n % i == 0:
			n_lst.append(i)

	res = sum(n_lst)  #완전수 판별식

	if res == n:

		res2 = f"{n} = {' + '.join(map(str, n_lst))}"
		print(res2)
	else :
		print(f"{n} is NOT perfect.")

정리

설계

  • while True(무한루프)로 테스트 케이스 부분 해결하자
  • -1가 들어왔을 때 break로 빠져나오자
  • 약수 리스트를 생성하자
  • 약수를 더해서 완전수 판별하자

몰랐거나 틀린 포인트

1. range()
- range(a, b)는 a 이상 b 미만이므로, 문제 조건에 맞춰 자연스럽게 자기 자신이 제외됨
- 이 부분을 자꾸 까먹어서 n+1을 했다가 자기 자신을 제외하는 과정에서 계산 과정이 또 들어감
- range(start, end) : start부터 end-1
- range(1, n) : 1부터 n-1
- range(n) : 0부터 n-1

2. map()함수
- map(str, n_lst)
- n_lst를 문자열로 변환 => 처음에 입력값 받을 때 의무적으로만 사용하고, 이 함수를 응용할 생각을 할 수 없었음
- 문제 조건에서 특정 출력 조건이 있을 때, 형을 변환해서 사용할 생각을 했어야 함

map(function, iterable)
- iterable 원소를 function에 넣어서 처리하는 함수
- 그러니까 반복 가능한 iterable에 함수를 적용시키는 역할을 함
- 형 변환 말고 다른 곳에도 쓸 수 있음
- 예시 (숫자 리스트에 함수 적용)

def square(x):
	return x * x;
    
nums = [1, 2, 3, 4, 5]
res = map(square, nums)
print(list(res)) # [1, 4, 9, 16, 35]

3. "separator".join() 함수
-"separator".join(iterable_of_strings)
- 문자열들의 리스트를 **하나의 문자열로 합칠 때** 사용
- 합칠 때 각 문자열 사이에 .join을 호출한 문자열(구분자, separator)을 넣어 줌
- .join()에 들어가는 iterable의 모든 원소는 문자열이어야 함
- 정수, 실수 등이 있으면 map(str, iterable)로 변환 과정 필요
- 예시
words = ["Hello", "world", "!"]
res = " ".join(words)
print(res) # 출력 Hello world !

4. f-string (formatted string literal)

- f"문자열 {변수명} 문자열 {표현식}"
- 문자열 앞에 f(or F)를 붙야 **문자열 안에 변수 값이나 표현식 결과를 직접 삽입**하는 방법
- "{}" 중괄호 안에 변수명 or 표현식을 넣으면 해당 값이 문자열에 바로 삽입
- 예시
name = "Alice"
age = 30

print(f"My name is {name} and I'm {age} years old.")
# My name is Alice and I'm 30 years old.

1978

내 풀이

# 1978번 소수 판별 문제 - 내 풀이 & 정리

---

## 1. 내 풀이

```python
N = int(input())
lst = map(int, input().split())
count_n = 0 # 소수 개수 카운팅 변수

for i in lst:
    if i == 1:
        continue  # 1은 소수가 아님
    else:
        root_n = int(i ** 0.5)  # i의 제곱근 구하기

        for j in range(2, root_n + 1):
            if i % j == 0:
                break  # 소수가 아니므로 판별 종료
        else:
            count_n += 1  # for문이 break 없이 정상 종료되면 소수이므로 카운팅

print(count_n)

정리

설계

-먼저 수의 개수 N을 입력 받음 (판별을 총 N번 할 것이기 때문)
-N개의 숫자를 입력받아 리스트 형태로 저장
-리스트의 각 원소(숫자)를 하나씩 순회하며 소수인지 판별
-1은 소수가 아니므로 바로 continue 처리
-각 숫자 i에 대해 2부터 √i까지 나눠서 나머지가 0이면 소수가 아님
-√i까지 나눠서 나눠떨어지지 않는다면 소수로 간주
-소수 개수를 세는 변수를 만들어 소수일 때마다 +1
-모든 수에 대해 판별을 마치면 소수 개수를 출력

몰랐거나 틀린 포인트

1. i가 리스트 내의 원소인지 인덱스인지?
- 파이썬에서 for i in lst:의 i는 리스트 원소의 값
- 자바에서 for(int i =0; i <lst.length; i++)의 i는 인덱스
- 파이썬에서 원소값에 접근할 땐 그냥 i를 씀, 인덱스가 필요할 떄 for idx, val inenumerate(lst): 사용

2. continue와 break (3번 for-else 구문과 합쳐져서 헷갈림)
- continue는 반복를 건너뛰고 **다음 반복**으로
- break는 **반복문 자체 종료**

3. for-else 구문 = "모든 반복이 정상적으로 끝나면 else 실행"
- else 블록을 조건문처럼 생각 X
- for문이 **break문 없이 정상 종료할 경우** 실행
- 나누어 떨어질 때 break로 루프 탈출 => else 실행 X
- 모든 나눗셈이 실패하면 => else 실행 

4. 루트 n
4-1 거듭제곱 연산자 **
- n의 제곱근 = n ** 0.5

4-2 math 모듈 sqrt() 함수
- math.sqrt() : 제곱근을 계산해 주는 함수
import math

n = 16
root_n = math.sqrt(n)
print(root_n)

5. flag 변수를 이용한 소수 판별 (이거 내가 아직 응용할 수 있을지 모르겠음)
N = int(input())
lst = map(int, input().split())
count_n = 0  # 소수 카운팅 변수

for i in lst:
    if i == 1:
        continue  # 1은 소수가 아님

    flag = True  # 소수라고 가정하고 시작
    root_n = int(i ** 0.5)

    for j in range(2, root_n + 1):
        if i % j == 0:
            flag = False  # 나눠떨어지는 수가 있으므로 소수 아님
            break  # 더 이상 검사할 필요 없음

    if flag:
        count_n += 1  # 소수일 때만 카운팅 증가

print(count_n)

- flag 변수를 사용해서 flag의 True or False의 결과에 따라 조건문을 하나 더 만들어서 거기에서 계산을 따로 처리하는 느낌?

2581

내 풀이

M = int(input())
N = int(input())

lst = []
lst2 = []
sum_num = 0

for i in range(M, N + 1):
	lst.append(i)

#M부터 N까지 자연수 리스트 lst

#소수 판별 => 소수면 더함


for i in lst:
	
	if i == 1 :
		continue

	num = int(i ** 0.5)

	for j in range (2, num + 1):
		if i % j == 0:
			break
	else:
		lst2.append(i)
		sum_num = sum_num + i

if lst2:
	print(sum_num)
	print(min(lst2))

else:
	print(-1)

정리

설계

- M부터 N까지 자연수 리스트를 생성
- 각 수에 대해 소수 여부를 판별:
  - 1은 소수가 아니므로 제외
  - 2부터 √i까지 나누어떨어지는 수가 있는지 검사
  - 나눠떨어지지 않으면 소수로 판별
- 소수라면 리스트에 저장 및 합산
- 마지막에 합과 최소값 출력

몰랐거나 틀린 포인트

1. 런타임 에러 => 소수가 없을 경우 -1을 출력해야 하는 조건 처리 X
- 예외 처리를 어떻게 해 줘야 하는가?
- if lst2: 사용 <= 리스트가 비었으면 False, 있으면 True
- 자바에서 if(!lst.isEmpty())

2. 논리는 위의 문제 때문에 맞았는데 들여쓰기로 틀린 게 많음
- 파이썬은 괄호 같은 게 없어서 들여쓰기 신경을 많이 써야 함

11653

내 풀이

M = int(input())

i = 2

while M != 1:

	if M % i == 0:
		M = M // i
		print(i)
	else:
		i += 1

정리

설계

1. N을 입력 받는다.  
2. `while N != 1:` 조건으로 반복문을 돌린다.  
3. `i`를 2부터 시작해 N까지 오름차순으로 나눌 수 있는지 검사한다.  
- 처음에 for문을 쓰려고 했으나 i 증가 문제 있음
- while을 사용하면 i 증가 조건을 달지 않는 이상 i의 값이 유지되므로 while을 사용하는 걸로 수정
4. `N % i == 0`이면  
   - **소인수** `i`를 출력  
   - `N = N // i` 으로 N을 갱신  
   - `i`는 그대로 두고(다시 같은 `i`로 나눌 수 있게) 반복문 계속  
5. `N % i != 0`이면  
   - `i += 1`로 다음 수 시도  
6. N이 1이 되면 반복 종료  

몰랐거나 틀린 포인트

1. for vs while
- 무조건 for문을 사용해서 해결하려고 하지 X
- for i in range()는 i가 자동 증가
- while은 i를 수동 조절 가능
- i를 무조건 증가시켜야 하는 상황이 아니라면 while 사용을 고려하기

2. 정수 나눗셈 연산자
- / = float 반환
- // = int 반환 (소인수분해하는 대상이 정수여야 하므로)
- N = int(N/i)는 안 돼? => 되는데 정확성, 성능, 가독성 구림

3. 소인수분해 코드 (통으로 이해하고 외우고 있으면 써먹을 곳 있긴 할 듯?)
N = int(input())
i = 2
while N != 1:
	if N % i == 0:
    	print(i)
        N = N // i
    else:
    	i += 1
profile
기술 블로그

0개의 댓글