본문바로가기
[오일러 프로젝트] 수 퀴즈 온더 블럭: 500개 이상의 약수를 갖는 가장 작은 삼각수는 무엇일까?
수학동아 2020.08.28 01:15 조회 1314

 

코.알.못 홍 기자의 코딩 도전기

코딩의 ‘코’자도 모르는 코.알.못. 홍 기자가 수학 문제를 코딩으로 푸는 오일러 프로젝트 문제를 하나하나 해결해 나갈 예정입니다. 오일러 프로젝트는 수학과 프로그래밍 실력을 모두 키울 수 있도록 2001년에 만든 수학 문제 웹사이트입니다. 홍 기자와 함께한다면 수학과 파이썬 모두 정복할 수 있지 않을까요?

 

 

홍아름 기자와 레온하르트 오일러가 여러분을 미션의 주인공으로 모십니다!

해야 할 미션은 한 가지, 1분 안에 문제의 답을 찾기만 하면 됩니다.

단, 코딩으로만 풀어야 하죠.

수학동아 자기님들! 오일러 프로젝트 문제 한번 풀어보실래요~?

 

 

<오일러 프로젝트 12번>

삼각수는 n(n+1)/2 공식으로 구할 수 있어요.

n에 1부터 차례대로 넣으면 다음과 같습니다.

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, …

그렇다면 500개 이상의 약수를 갖는 가장 작은 삼각수는 무엇일까요?

 

지난 45번 문제에 이어 또 다시 삼각수가 등장했습니다. 삼각수는 말 그대로 삼각형 형태를 만드는 데 필요한 점의 개수로, 1부터 시작한 연속된 자연수의 합이기도 합니다. 이번 12번 문제에서는 삼각수의 약수 개수도 구해야 합니다.

약수는 어떤 수를 나눴을 때 나눠떨어지게 하는 자연수로, 어떤 자연수 n의 약수의 개수는 n보다 작은 자연수로 일일이 나눠보며 찾을 수 있죠. 60의 약수를 한번 찾아볼까요?

 

 

이때 1과 60, 2와 30, 3과 20, 4와 15, 5와 12, 6과 10으로 둘씩 짝지어지는 것을 알 수 있습니다. 따라서 60의 경우는 6개의 자연수만 확인해보면 약수의 개수를 찾을 수 있죠. 즉 자연수 n의 약수를 찾을 때 n보다 작은 모든 자연수 대신 √n보다 작거나 같은 자연수로만 나눠보면 약수를 찾을 수 있습니다.

이 방법을 코드로 나타내 12번 문제를 해결해보겠습니다!

 

 

파이썬 완전정복! 필수 명령어

 

1. 약수의 개수를 구하는 함수 만들기

어떤 자연수 n이 √n보다 작은 자연수로 나눠떨어지는지를 보고, 약수의 개수를 찾는 함수 num_factors(n)을 만들겠습니다. 변수 f를 약수의 개수, in을 나눌 수라고 할 때 fi 초깃값은 모두 2입니다. 그리고 ii2n보다 작거나 같을 때까지 1씩 늘려가며 n을 나눠떨어지게 하는지 확인합니다.

 

 

2. num_factors(n) 함수로 답 얻기

자연수의 약수의 개수를 찾는 함수에 삼각수를 대입해 답을 찾습니다. 이때 k번째 삼각수를 구하는 식 k(k+1)/2을 이용하는데, 이 식은 1부터 k까지의 자연수를 모두 더한 값을 구하는 공식과 같습니다. 따라서 k번째 삼각수를 구할 때 매번 1부터 k까지의 수들의 합을 구할 필요 없이, k-1번째 삼각수에 k를 더하기만 하면 되죠. 코드에서는 k번째 삼각수 t가 500개보다 작은 약수의 개수를 갖는다면, 그다음 k+1번째 삼각수를 구하기 위해 tk+1을 더한 뒤 다시 약수의 개수를 구합니다. 이 과정을 반복해 약수가 500개 이상인 수를 찾으면 while 문에서 나와 정답을 출력합니다.

 

 

 

도전! 오일러 프로젝트 12번 문제 뽀개기

* 코딩 언어는 Python으로 두고 실행하세요!

 

 

#1~7  약수의 개수를 얻는 num_factors(n) 함수를 정의합니다.

#8 num_factors(n) 함수를 사용해 오일러 프로젝트 12번 문제의 답을 찾는 함수 e012()를 정의합니다.

#9 삼각수 t의 초깃값은 1이고, 첫 번째 삼각수이므로 순번을 나타내는 k의 초깃값을 1로 둡니다.

#10~11 삼각수 t의 약수의 개수가 500개보다 적다면, tk+1을 더해 다음 k+1번째 삼각수를 구하고, while문을 반복합니다.

#12 약수의 개수가 500개 이상이면 while문을 벗어나고, 이때의 t를 돌려줍니다.

#13 함수 e012()를 실행해 답을 얻습니다.

 

 

Bonus! 오일러 퀴즈

 

오일러 프로젝트 12번 문제를 위 코딩창에서 풀어보고, 다음 예제 문제에도 도전해보세요!

 

① 약수의 개수가 500개 이상인 가장 작은 오각수를 찾아보자.

Hint. n번째 오각수 = n(3n-1)/2

 

② 소인수분해를 이용해 약수의 개수를 구하는 코드를 만들어보자.

Hint. 어떤 자연수가 ap×bq×cr으로 소인수분해되면, 약수의 개수는 (p+1)(q+1)(r+1)이다.

 

 

이번 해답 코드를 이용해 12번 문제의 답을 찾으면 7~8초 정도가 걸립니다. 물론 1분 이내이긴 하지만, 프로 코딩러라면 몇 초 동안 멍하니 기다리는 것도 고역이죠! 삼각수의 성질을 이용해 더 빨리 계산할 수 있는 꿀팁을 알려드릴게요!

 

 

----------------------------------------꿀팁 구간----------------------------------------

 

 

삼각수를 구하는 식 k(k+1)/2의 식을 보면, 서로소인 두 수 k와 (k+1)의 곱으로 이뤄져있습니다. 만약 k가 짝수라면 k+1은 홀수, 반대로 k가 홀수라면 k+1은 짝수가 되죠. 어느 쪽이건 짝수인 쪽을 2로 나누면 삼각수는 서로소인 두 숫자의 곱으로 나타낼 수 있습니다. 

이 서로소인 두 수를 a, b라고 할 때, 삼각수의 약수 개수는 (a의 약수 개수)×(b의 약수 개수)와 같습니다. 따라서 삼각수보다 작은 자연수로 일일이 나눌 필요 없이 삼각수를 이루는 a, b를 구해 각각의 약수 개수를 구하고 곱하면 됩니다. 이 방법을 이용한 것이 아래의 코드로, 얼마나 빨라지는지 한번 실행해보세요!

 

 

  • 폴리매스 문제는 과학기술진흥기금 및 복권기금의 재원으로 운영되고, 과학기술정보통신부와 한국과학창의재단의 지원을 받아 수행된 성과물로 우리나라의 과학기술 발전과 사회적 가치 증진에 기여하고 있습니다.

  • ☎문의 02-6749-3911