약수(divisor, factor): 어떤 수를 나누어떨어지게 하는 수
-Reference. Divisor
따라서, 자연수 의 약수는 자연수 n을 자연수 1부터 n으로 차례대로 나누었을 때 나누어떨어지게 하는 자연수
들이다.
따라서 약수들의 리스트를 구하는 알고리즘을 파이썬으로 구현하면 다음과 같다.
def is_divisor(factor: int, n: int) -> boolean:
if n % factor == 0:
return True
else:
return False
def get_divisors(n: int) -> list:
divisors = []
for i in range(1, n + 1):
if is_divisor(i, n):
divisors.append(i)
return divisors
get_divisors(10)
>>> [1, 2, 5, 10]
따라서, 자연수 의 약수의 개수는 자연수 n을 자연수 1부터 n으로 차례대로 나누었을 때 나누어떨어지게 하는 자연수의 개수
이다.
따라서, 위의 1.1. 약수 판별 알고리즘을 활용하여 약수의 개수를 구하는 알고리즘을 파이썬으로 구현하면 다음과 같다.
def is_divisor(factor: int, n: int) -> boolean:
if n % factor == 0:
return True
else:
return False
def num_divisors(n: int) -> int:
count = 0
for i in range(1, n + 1):
if is_divisor(i, n):
count += 1
return count
num_divisors(10)
>>> 4
위의 1.1. 약수 판별 알고리즘과 1.2. 약수의 개수 알고리즘을 활용하여 다음과 같이 파이썬으로 문제를 풀이할 수 있다.
import sys
def is_divisor(factor: int, n: int) -> bool:
if n % factor == 0:
return True
else:
return False
def get_divisors(n: int) -> list:
divisors = []
for i in range(1, n + 1):
if is_divisor(i, n):
divisors.append(i)
return divisors
N, K = list(map(int, sys.stdin.readline().split()))
divisors = get_divisors(N)
if len(divisors) < K:
print(0)
else:
print(divisors[K + 1])
소인수분해(prime factorization, integer factorization): 1보다 큰 자연수를 소인수(소수인 인수)들의 곱으로 나타냄. 합성수(1보다 큰 자연수 중에서 소수가 아닌 수)를 소수(1보다 큰 자연수 중 1과 자기 자신만을 약수로 가지는 수)의 곱으로 나타냄.
-Reference. Integer factorization
따라서, 자연수 의 소인수분해는 자연수 n을 1보다 큰 소수부터 n의 제곱근보다 작거나 같은 소수를 차례대로 나누었을 때 나누어떨어지게 하는 자연수
이다.
따라서, 위의 1. 일반적인 방법을 활용하여 소인수분해하는 알고리즘을 파이썬으로 구현하면 다음과 같다.
import math
def is_divisor(factor: int, n: int) -> bool:
if n % factor == 0:
return True
else:
return False
def is_prime_number(n: int) -> bool:
if n == 2:
return True
for i in range(2, n):
if is_divisor(i, n):
return False
return True
def get_prime_numbers(limit: int) -> list:
prime_numbers = []
for i in range(2, limit + 1):
if is_prime_number(i):
prime_numbers.append(i)
return prime_numbers
def get_prime_factors(n: int) -> dict:
prime_factors = dict()
for i in get_prime_numbers(int(math.sqrt(n))):
while is_divisor(i, n):
prime_factors[i] = prime_factors.get(i, 0) + 1
n //= i
return prime_factors
get_prime_factors(17)
>>> {}
get_prime_factors(12)
>>> {2: 2, 3: 1}
따라서, 자연수 의 약수의 개수는 자연수 n을 소인수분해한 인수들의 곱으로 만들 수 있는 자연수의 개수
이다.
따라서, 위의 2.1. 소인수분해 알고리즘을 활용하여 약수의 개수를 구하는 알고리즘을 파이썬으로 구현하면 다음과 같다.
import math
def is_divisor(factor: int, n: int) -> bool:
if n % factor == 0:
return True
else:
return False
def is_prime_number(n: int) -> bool:
if n == 2:
return True
for i in range(2, n):
if is_divisor(i, n):
return False
return True
def get_prime_numbers(limit: int) -> list:
prime_numbers = []
for i in range(2, limit + 1):
if is_prime_number(i):
prime_numbers.append(i)
return prime_numbers
def num_prime_factors(n: int) -> int:
prime_factors = dict()
for i in get_prime_numbers(n):
while is_divisor(i, n):
prime_factors[i] = prime_factors.get(i, 0) + 1
n //= i
return sum(prime_factors.values())
get_prime_factors(17)
>>> 0
get_prime_factors(12)
>>> 3
위의 2.1. 소인수분해 알고리즘을 활용하여 다음과 같이 파이썬으로 문제를 풀이할 수 있다.
import sys
import math
def is_divisor(factor: int, n: int) -> bool:
if n % factor == 0:
return True
else:
return False
def is_prime_number(n: int) -> bool:
if n == 2:
return True
for i in range(2, n):
if is_divisor(i, n):
return False
return True
def get_prime_numbers(limit: int) -> list:
prime_numbers = []
for i in range(2, limit + 1):
if is_prime_number(i):
prime_numbers.append(i)
return prime_numbers
def print_prime_factors(n: int) -> None:
prime_factors = dict()
for i in get_prime_numbers(n):
if n == 1:
break
while is_divisor(i, n):
print(i)
n //= i
print_prime_factors(int(sys.stdin.readline().split()[0]))
하지만, 소수를 먼저 계산하여 리스트로 담아두고 계산하는 방법
은 너무 많은 반복문을 사용하여 시간 초과가 뜬다.
자연수들의 인수는 해당 자연수보다 작은 소수들의 곱으로 이루어져있다. 따라서, 작은 소수부터 주어진 자연수의 약수인지 검사한다면, 합성수는 자연스럽게 제거되므로 소수를 먼저 계산하여 리스트로 담아두고 계산하는 방법
을 사용하지 않아도 된다.
이를 반영하여 다음과 같이 파이썬으로 문제를 풀이할 수 있다.
import sys
import math
def is_divisor(factor: int, n: int) -> bool:
if n % factor == 0:
return True
else:
return False
def print_prime_factors(n: int) -> None:
i: int = 2
while n != 1:
while is_divisor(i, n):
print(i)
n //= i
i += 1
print_prime_factors(int(sys.stdin.readline().split()[0]))