我一直在尝试解决这个问题——我试了几次才弄明白这个问题。我想在我放弃之前写下我学到的东西并转向更简单的事情!
首先,我对@shiva 的解决方案进行了修改,该解决方案可以更快地产生正确的输出:
import sys
from functools import lru_cache
def sum_of_digits(number):
summation = 0
while number > 0:
summation += number % 10
number //= 10
return summation
@lru_cache()
def is_prime(number):
if number < 2:
return False
if number % 2 == 0:
return number == 2
divisor = 3
while divisor * divisor <= number:
if number % divisor == 0:
return False
divisor += 2
return True
maximum = int(sys.argv[1])
count = 0
for i in range(maximum + 1):
sum_i = sum_of_digits(i)
for j in range(i, maximum + 1):
if is_prime(sum_i + sum_of_digits(j)):
count += 1
print(count)
我将此作为以下速度和准确性的基准。
所需的素数是微不足道的,即使是 10^50,也可以/应该提前计算。生成的数字和的数量也相对较少,可以存储/散列。我的解决方案将所有可能的数字和从 0 到 10^N 散列,存储每个和的生成次数作为值。然后它在数字和(键)上执行一对嵌套循环,如果这些和的总和是素数,它将每个总和可以计算的方式数的乘积添加到计数中(即乘以值)。
import sys
from math import ceil
from collections import defaultdict
VERBOSE = False
def sum_of_digits(number):
summation = 0
while number:
summation += number % 10
number //= 10
return summation
def sieve_primes(n):
sieve = [False, False] + [True] * (n - 1)
divisor = 2
while divisor * divisor <= n:
if sieve[divisor]:
for i in range(divisor * divisor, n + 1, divisor):
sieve[i] = False
divisor += 1
return [number for number in range(2, n + 1) if sieve[number]]
power = int(sys.argv[1]) # testing up to 10 ** power
maximum_sum_of_digits = 18 * power
primes_subset = sieve_primes(maximum_sum_of_digits)
sums_of_digits = defaultdict(int)
for i in range(10 ** power + 1):
sums_of_digits[sum_of_digits(i)] += 1
if VERBOSE:
print('maximum sum of digits:', maximum_sum_of_digits)
print('maximum prime:', primes_subset[-1])
print('number of primes:', len(primes_subset))
print('digit sums cached', len(sums_of_digits))
primes_subset = set(primes_subset)
count = 0
for i in sums_of_digits:
sum_i = sums_of_digits[i]
for j in sums_of_digits:
if i + j in primes_subset:
count += sum_i * sums_of_digits[j]
print(ceil((count + 2) / 2)) # hack to help adjust between duples and no duples count; sigh
(打开VERBOSE 标志以查看有关该问题的更多信息。)
不幸的是,这与问题规范相反,这同时计算了 (X, Y) 和 (Y, X),因此在代码末尾有一个近似的更正技巧来对此进行调整。 (请提出一个精确的更正!)我称我的结果为近似值,但它通常只少算 1 或 2。与@shiva 的代码不同,这个以 10 的幂作为参数,因为它的目标是查看接近 10 ^ 50就可以了。
很高兴看到 N=10^50(或至少 10^8)的结果 – MBo
@Shiva reworked My Attempt
exact secs approx secs
10^1 24 0.03 24 0.03
10^2 1544 0.04 1544 0.04
10^3 125030 0.49 125029 0.04
10^4 12396120 51.98 12396119 0.05
10^5 1186605815 6223.28 1186605813 0.14
10^6 113305753201 1.15
10^7 11465095351914 12.36
10^8 1120740901676507 137.37
10^9 105887235290733264 1626.87
@shiva 改进后的解决方案在 10^4 以上时毫无用处,而在 10^8 以上时我会陷入困境。所以达到 10^50 将采取不同的方法。我希望其中的一些代码和分析将有助于实现这一目标。