위의 의견을 기반으로 한 해결책이 있습니다. 나는 이것이 최적이라고 주장하지 않습니다.
아이디어는 을 고려하는 것이며 , 이는 "정확히 제수와 개의 고유 한 소수를 가진 가장 작은 양의 정수"로 정의됩니다 . 우리는 쉽게 관찰합니다 :T(n,m)nm
T(n,1)T(2m,m)=2n−1=p1p2⋯pm
그리고 우리는 또한 재발이 있습니다.
T(n,m)=mind|n[T(nd,m−1)⋅pd−1m]
마지막으로, 찾고자하는 수량은
min1≤i≤⌈log(n)⌉T(n,i)
이를 위해 여기에 주어진 모든 숫자와 일치하는 Python 코드가 있습니다. 로그와 함께 작동하여 숫자를 작게 유지합니다. 따라서 실제 정수는 round(2**smallest(n))
입니다.
import functools
import itertools
import math
# All primes less than 100.
PRIMES = [
2, 3, 5, 7, 11,
13, 17, 19, 23, 29,
31, 37, 41, 43, 47,
53, 59, 61, 67, 71,
73, 79, 83, 89, 97,
]
LOG_PRIMES = [math.log2(p) for p in PRIMES]
def smallest(n):
max_factors = math.ceil(math.log2(n))
min_so_far = float('Infinity')
factors = factorize(n)
memo = {}
for i in range(1, max_factors+1):
t = T(n,i, factors, memo)
if 0.0 < t < min_so_far:
min_so_far = t
return min_so_far
def T(n, m, factors=None, memo=None):
if memo is None:
memo = {}
if n < 2 or m < 1:
return 0
elif m == 1:
# Everything on the smallest prime.
return (n-1) * LOG_PRIMES[0]
elif n < 2**m:
return 0
elif n == 2**m:
# Product of first m primes, in log.
return sum(LOG_PRIMES[:m])
elif (n,m) in memo:
return memo[(n,m)]
if factors is None:
factors = factorize(n)
if len(factors) < m:
return 0
smallest = float('Infinity')
for factor_list in powerset(factors):
divisor = product(factor_list)
first = T(divisor, m-1, factor_list, memo)
# No such product.
if first < 1.0:
continue
second = (n/divisor - 1) * LOG_PRIMES[m-1]
total = first + second
if total < smallest:
smallest = total
memo[(n,m)] = smallest
return smallest
def product(nums):
return functools.reduce(lambda x,y: x*y, nums, 1)
def factorize(n):
prime_factors = []
for p in PRIMES:
while n%p == 0:
n //= p
prime_factors.append(p)
if n == 1:
break
return prime_factors
def powerset(lst):
# No empty set.
return itertools.chain.from_iterable(itertools.combinations(lst, r)
for r in range(1, len(lst)+1))