일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- NumPy
- Big Omega
- recursive algorithms
- linear dependence
- python
- 빅세타
- 재귀함수
- Big-Oh notation
- 랜덤 순서 배열
- 배열 섞기
- nonhomogeneous linear system
- 이진 탐색
- Big-Oh 예제
- one-to-one
- 빅오메가
- nontrivial solution
- 코틀린 시작하기
- includepdf
- 일차변환
- Big-O 예제
- trivial solution
- matrix trnasformations
- itertools
- 코틀린 Hello World!
- 빅오 표기법
- 알고리즘 분석의 실례
- Big Theta
- homogeneous linear system
- 페이지 겹칩
- matrix fo a linear transformation
- Today
- Total
코딩 연습
프로젝트 오일러 132번 본문
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,⋯ 이다. 아마 한국에서 고등학교를 제대로(?) 졸업했다면 이 수열의 일반항이 10n−19 라는 것 쯤은 알고 있을 것이라 믿어 의심치 않는다. 그렇다면 10n−19 이 p 로 나누어 떨어지는 소수 p 들을 찾으면 된다. 소수 p 로 나누었을 때의 몫을 Q 라고 하면 10n−19=Qp 가 성립할 것이고, 결국 10n=Q×(9p)+1 이 된다. 즉, 10n 을 9p 로 나누었을 때의 나머지가 1 이 되는 소수 p 들을 찾으면 된다.
그런데 이 문제에서는 n=109 인 경우를 다뤄야 한다. 설명은 쉬웠지만 10109 을 9p 로 나눈다는 것 자체가 상당히 어려운 일이다. 제 아무리 컴퓨터라 할지라도... 그래서 우리는 거듭제곱을 어떤 수로 나눈 나머지를 더욱 빠르게 구할 수 있는 방법에 대해서 생각해 봐야 한다.
이를 위하여 우리는 다음의 두 가지를 알고 있어야 한다.
1. ab 를 m 으로 나눈 나머지는 a 를 m 으로 나눈 나머지와 b 를 m 으로 나눈 나머지의 곱이다.
2. 거듭제곱을 빠르게 하기 위한 방법
be 을 빠르게 구하기 위해서는 e=n−1∑i=0ai2i 의 형태로 표현한다. 즉, be=bn−1∑i=0ai2i=n−1∏i=0(b2i)ai
로 표현하는 것이다. 또한 이 과정에서 be 을 m 으로 나눈 나머지를 구할 때는, 위의 1번 성질을 이용하여 곱하는 놈과 곱해지는 놈을 m 으로 나눈 나머지들을 곱하여 그 결과를 다시 m 으로 나눈 나머지를 구하는 방식으로 쉽게 나머지를 구할 수 있다.
다음의 파이썬 코드는 위의 두 가지 성질을 이용하여 be 을 m 으로 나눈 나머지를 구하는 함수이다.
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 이 나머지를 나타내는데, 고등학교 수학 시간에 순서도 공부하듯이, r 과 b 의 테이블을 만들어 변화 과정을 살펴보면 충분히 이해가 갈 것이다.
파이썬에서는 위의 예제 코드에서 보여지는 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 |