【问题标题】:Count number of pairs of two numbers less than or equal to N such that Sum of the digits of numbers of pair is Prime计算小于或等于 N 的两个数的对数,使得对数的数字之和为素数
【发布时间】:2019-09-25 18:58:50
【问题描述】:

给定一个数 N,计算所有对 (X,Y),使得 X 和 Y 的数字之和为素数。条件如下。

  • 1
  • 0
  • (X,Y) 和 (Y,X) 是同一对。

我可以想到蛮力方法。我需要在其中放置两个从 1 到 N 的循环,并计算每个 x 和 y 对的数字总和,并检查它是否为素数。但它不是最佳解决方案,因为 N 的范围为 10^50。

【问题讨论】:

  • 您使用什么语言?到目前为止,您尝试过什么?
  • 问题与语言无关,虽然我已将 Java 添加为语言
  • 考虑 X 和 Y 最多有 100 个数字,每个数字最多为 9。因此最大数字和为 9000,最小当然为 0。现在循环遍历 [0 中的每个素数, 9000] 并计算有多少种方式可以将这个素数划分为两个(最多)50 位数字。
  • 您能否更具体地了解分区,或者您能否提供数学公式来计算(因为每个分区可以满足不同的数字)。
  • @JamesKPolk,我可能很密集,但我不明白为什么 100 位数字的最大总和是 9000 而不是 900——我错过了什么?

标签: java algorithm primes discrete-mathematics number-theory


【解决方案1】:

试试这个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);

示例输出:

【讨论】:

  • 很高兴看到 N=10^50(或至少 10^8)的结果
  • 您应该考虑 X 和 Y 的范围。这不是最佳解决方案。
  • 未优化,但 X 和 Y 在范围内。你能告诉我 X、Y 不在范围内吗?
  • X 的值可以从 1 到 10^50。只要蛮力无济于事。
  • 如果我正确读取输出,这个解决方案会错误地在素数集中包含 1?
【解决方案2】:

我一直在尝试解决这个问题——我试了几次才弄明白这个问题。我想在我放弃之前写下我学到的东西并转向更简单的事情!

首先,我对@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 将采取不同的方法。我希望其中的一些代码和分析将有助于实现这一目标。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 2021-11-27
    • 2017-10-07
    相关资源
    最近更新 更多