Wireframe

오일러 프로젝트 27

오일러는 다음과 같은 멋진 2차식을 제시했습니다.

이 식의 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의 범위를 축소할 수 있다.


이 조건을 사용하면 계산량을 비약적으로 줄일 수 있다.

# 소수검사
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)
Exit mobile version