한국어/Hackerrank - 한국어 버전과 문제가 다를 수 있습니다. 채점은 Hackerrank를 추천합니다.
N개의 양의 정수가 주어질때 각 숫자보다 작은 3과 5의 배수의 합을 출력하는 문제
(조건: 입력받는 수의 개수 N, 입력받은 수 M)
def get_sum_of_mutiples(num, target):
amt = num//target
return target*amt*(amt+1)//2
for _ in range(int(input())):
m = int(input())
total = get_sum_of_mutiples(m-1, 3) + get_sum_of_mutiples(m-1, 5) - get_sum_of_mutiples(m-1, 15)
print(total)
# amt_threes, amt_fives, amt_fifteens = (m-1)//3, (m-1)//5, (m-1)//15
# total = (3*amt_threes*(amt_threes+1) + 5*amt_fives*(amt_fives+1) - 15*amt_fifteens*(amt_fifteens+1))//2
이 문제는 단순하게 풀자면 이중 반복문을 통해 N번 반복하며 1부터 M까지 돌며 3과 5의 배수들을 일일히 더할 수도 있다.
그러나 이 방식은 O(N*M)의 복잡도를 가지게 되며 Hackerrank의 입력 범위를 보면 최악의 경우 10^14번 돌아야 한다는 것을 알 수 있다.
하지만 이 문제는 O(N)으로 풀 수 있는데 바로 위의 코드가 그 방법이다.
문제를 살짝 바꿔서 3과 5의 배수의 개수를 찾는 문제라고 가정해봅시다.
그러면 간단히 (M-1)//3+(M-1)//5-(M-1)//15으로 구할 수 있습니다. (M-1인 이유는 M은 포함하지 않기 때문입니다.)
여기서 (M-1)//3을 T라고 두면 3의 배수의 합은 3*1+3*2+3*3+....+3*T이고 이는 3*(1+2+3+...+T)가 됩니다.
수학적으로 1부터 N까지의 값은 N*(N+1)/2로 구할 수 있습니다.
그러므로 위 식은 3*T*(T+1)/2가 되고 T와 T+1중 하나는 짝수이므로 3*T*(T+1)//2로 3의 배수의 합을 구할 수 있습니다.
이를 통해 5의 배수의 합은 5*T*(T+1)//2, 15의 배수의 합은 15*T*(T+1)//2로 구할 수 있습니다.(여기서 T는 M보다 작은 특정 수의 배수)
위의 코드는 M보다 작은 어떤 수의 배수의 합을 함수화한 것이며 코드 밑의 주석은 함수를 없앤 코드이다.
'알고리즘 공부 > 프로젝트 오일러(Project Euler)' 카테고리의 다른 글
{프로젝트 오일러/Project Euler} 6. 제곱의 합과 합의 제곱의 차 (0) | 2021.01.03 |
---|---|
{프로젝트 오일러/Project Euler} 5. 1~ N으로 나누어 떨어지는 수 (0) | 2021.01.02 |
{프로젝트 오일러/Project Euler} 4. 세자리 수를 곱해 만든 대칭수 (0) | 2021.01.01 |
{프로젝트 오일러/Project Euler} 3. 가장 큰 소인수 구하기 (0) | 2020.12.31 |
{프로젝트 오일러/Project Euler} 2. 짝수 피보나치 항의 합 (0) | 2020.12.31 |