오일러는 다음과 같은 멋진 2차식을 제시했습니다.
n^2 + n + 41이 식의 n에다 0부터 39사이의 숫자를 넣으면, 그 결과는 모두 소수가 됩니다. 하지만 n=40일 때의 값은 41로 나누어지고, n=41일 때 역시 41로 나누어지므로 소수가 아닙니다.
컴퓨터의 발전에 힘입어 n2 – 79n – 1601이라는 엄청난 2차식이 발견되었는데, 이것은 n이 0에서 79사이일 때, 모두 80개의 소수를 만들어냅니다. 이 식의 계수의 곱은 -79 × 1601 = -126479가 됩니다. 아래와 같은 모양의 2차식이 있다고 가정했을 때,(| a | < 1000, | b | < 1000) 0부터 시작하는 연속된 자연수 n에 대해 가장 많은 소수를 만들어내는 2차식을 찾아서 그 계수 a, b의 곱을 구하세요.
http://euler.synap.co.kr/prob_detail.php?id=27
접근
2차식의 그래프를 그려보면 포물선 모양임을 알 수 있다. 포물선은 꼭지점의 x 값을 기준으로 좌우로 대칭이므로, 어떤 이차식이 많은 소수를 만들기 위해서는 꼭지점을 중심으로 좌우로 대칭하게 소수가 분포하는 것이 가장 좋다. 따라서 포물선의 그래프는 좌표평면 위의 제1사분면에 존재해야 한다.
n2 + an + b 의 포물선의 꼭지점이 제 1사분면에 존재하기 위해서는 b > -2a 라는 조건을 만족해야 한다. 그리고 문제에서 a, b의 범위가 결정되었기 때문에, 다음의 범위로 a, b의 범위를 축소할 수 있다.
\begin{align} -2a &< b < 1000 \\ -500 &< a< 0 \end{align}
이 조건을 사용하면 계산량을 비약적으로 줄일 수 있다.
# 소수검사
def isprime(n: int) -> bool:
if n < 2:
return False
if n < 4:
return True
if n % 2 == 0 or n % 3 == 0:
return False
if n < 10:
return True
k, l = 5, int(n**.5 + 1.5)
while k < l:
if n % k == 0 or n % (k + 2) == 0:
return False
k += 6
return True
# 이차식 생성
def make_equation(a, b):
return lambda n: n * n + a * n + b
# 이차식으로부터 연속된 소수를 몇 개나 만들 수 있는지 확인
def test(a, b):
eq = make_equation(a, b)
n = 0
while True:
if isprime(eq(n)):
n += 1
else:
return n
# 풀이!
mc, res = 0, 0
for a in range(-500, 0):
for b in range(-2 * a + 1, 1000):
c = test(a, b)
if mc < c:
mc, res = c, a * b
print(res)