코딩 연습

프로젝트 오일러 132번 본문

project euler with python

프로젝트 오일러 132번

코딩아저씨 2016. 3. 15. 16:01
반응형

A number consisting entirely of ones is called a repunit. We shall define R(k) to be a repunit of length k.

For example R(10)=1111111111=11×41×271×9091, and the sum of these prime factors is 9414.

Find the sum of the first fort prime factors of R(109).




숫자 1 로만 이루어진 수를 repunit 이라고 한다. R(k)k 개의 1 로 이루어진 수라고 하자. 예를 들어, R(10)=1111111111 이다. 이 때, R(10)11×41×271×9091 로 소인수 분해 된다. 그리고 이들 소인수들의 총합은 9414 가 된다.

R(109) 의 소인수를 오름 차순으로 나열했을 때, 처음 40 개 소인수들의 합을 구하시오.  


고등학교 수학 시간에도 가끔 등장하는 수열이 1,11,111,111, 이다. 아마 한국에서 고등학교를 제대로(?) 졸업했다면 이 수열의 일반항이 10n19 라는 것 쯤은 알고 있을 것이라 믿어 의심치 않는다. 그렇다면 10n19 이 p 로 나누어 떨어지는 소수 p 들을 찾으면 된다. 소수 p 로 나누었을 때의 몫을 Q 라고 하면 10n19=Qp 가 성립할 것이고, 결국 10n=Q×(9p)+1 이 된다. 즉, 10n9p 로 나누었을 때의 나머지가 1 이 되는 소수 p 들을 찾으면 된다.


그런데 이 문제에서는 n=109 인 경우를 다뤄야 한다. 설명은 쉬웠지만 101099p 로 나눈다는 것 자체가 상당히 어려운 일이다. 제 아무리 컴퓨터라 할지라도... 그래서 우리는 거듭제곱을 어떤 수로 나눈 나머지를 더욱 빠르게 구할 수 있는 방법에 대해서 생각해 봐야 한다.


이를 위하여 우리는 다음의 두 가지를 알고 있어야 한다.


1. abm 으로 나눈 나머지는 am 으로 나눈 나머지와 bm 으로 나눈 나머지의 곱이다.


2. 거듭제곱을 빠르게 하기 위한 방법

be 을 빠르게 구하기 위해서는 e=n1i=0ai2i 의 형태로 표현한다. 즉, be=bn1i=0ai2i=n1i=0(b2i)ai

로 표현하는 것이다. 또한 이 과정에서 be 을 m 으로 나눈 나머지를 구할 때는, 위의 1번 성질을 이용하여 곱하는 놈과 곱해지는 놈을 m 으로 나눈 나머지들을 곱하여 그 결과를 다시 m 으로 나눈 나머지를 구하는 방식으로 쉽게 나머지를 구할 수 있다. 


다음의 파이썬 코드는 위의 두 가지 성질을 이용하여 bem 으로 나눈 나머지를 구하는 함수이다.

def exp_mod(b, e, m):
	r = 1
	result = list(bin(e))[2:]
	result.reverse()
	for i in range(len(result)):
		if result[i] == '1':
			r = r * b % m
		b = b * b % m
	return r

여기서 r 이 나머지를 나타내는데, 고등학교 수학 시간에 순서도 공부하듯이, rb 의 테이블을 만들어 변화 과정을 살펴보면 충분히 이해가 갈 것이다.


파이썬에서는 위의 예제 코드에서 보여지는 exp_mod 와 똑같은 역할을 하는 pow 함수를 기본으로 제공하고 있다. 속도는 pow 쪽이 더 빠르다. 둘을 비교해 보는 것도 재미가 쏠쏠할 듯...





반응형

'project euler with python' 카테고리의 다른 글

프로젝트 오일러 134번  (0) 2016.03.15
프로젝트 오일러 133번  (0) 2016.03.15
프로젝트 오일러 131번  (0) 2016.03.15
프로젝트 오일러 130번  (0) 2016.03.15
프로젝트 오일러 129번  (0) 2016.03.15


Comments