给出一个数字N,对所有对(X,Y)进行计数,以使X和Y的位数之和为质数。条件如下。
我可以想到暴力破解方法。在其中,我需要放置两个从1到N的循环,并计算每个x和y对的数字总和,并检查其素数。但是它不是最佳解决方案,因为N的范围是10 ^ 50。
答案 0 :(得分:1)
我一直在为此努力-我花了几次尝试才了解问题所在。我想写下自己在放弃之前学到的东西,然后转向更轻松的东西!
首先,我对@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将会采取另一种方法。我希望其中一些代码和分析将有助于实现这一目标。
答案 1 :(得分:0)
尝试以下python代码并进行调试:
def sumofdigits(num):
sum=0
while num>0:
sum+=num%10
num=num//10
return sum
def isprime(num):
if num==0:
return False
i = 2
while i<num:
if num%i==0:
return False
i+=1
return True
number = int(input("Enter number:"))
for i in range(0,number+1):
for j in range(i,number+1):
if isprime(sumofdigits(i)+sumofdigits(j)):
print(i,j);