【问题标题】:Need help in solving the following efficiently in terms of time complexity在时间复杂度方面需要帮助以有效地解决以下问题
【发布时间】:2016-07-23 23:17:56
【问题描述】:

最近两天我正在尝试解决以下问题。除了蛮力,我想不出任何解决方案。任何类型的提示或参考将不胜感激。 TIA。

"给定 N 个不同的素数,即p1p2、...、pN 和一个区间 [L,R]。计算此区间中至少可以被给定的一个整数整除的整数个数素数。”

N 非常小 (1

【问题讨论】:

  • 不可能,因为有 O(n) 个这样的数字(假设 n 是区间长度)。
  • @user4759923 给定素数(N)的数量将非常少。我们能以某种方式利用它吗?
  • 否,因为在可被 P1 整除的区间中有 O(n) 个数
  • 你对素数的大小有限制吗?与 L 和/或 R 相比,您的质数有多大?
  • 我认为复杂度是 O(nprimes * intervalLength)。你至少应该定义n的意思。

标签: algorithm performance complexity-theory


【解决方案1】:

首先注意,限制问题更容易,忽略下限(即:处理 L=1)。如果我们可以对任意 N 都可以被素数

给定任意数 x,可被 x 整除的数

现在,我们可以应用inclusion-exclusion principle 来获得结果。首先,我将手动显示 3 个素数 p1、p2 和 p3 的结果,然后给出一般结果。

可被 p1、p2 或 p3 整除的数字

R / p1 + R / p2 + R / p3
- R / (p1p2) - R / (p1p3) - R / (p2p3)
+ R / (p1p2p3)

(这里/假定为四舍五入整数除法)。

一般情况如下:

sum((-1)^(|S|+1) * R / prod(S) for S a non-empty subset of {p1, p2, .., pN}).

这里S 涵盖所有素数子集,prod(S) 是子集中素数的乘积,初始项根据子集的大小在 -1 和 +1 之间变化。

对于您的问题,N

这是一些 Python 代码示例:

from itertools import *

def powerset(iterable):
    s = list(iterable)
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

def prod(ns):
    r = 1
    for n in ns:
        r *= n
    return r

def divs(primes, N):
    r = 0
    for S in powerset(primes):
        if not S: continue
        sign = 1 if len(S) % 2 else -1
        r += sign * (N // prod(S))
    return r

def divs_in_range(primes, L, R):
    return divs(primes, R) - divs(primes, L-1)

请注意,此代码的运行时间或多或少仅取决于质数的数量,而与 L 和 R 的大小无关。

【讨论】:

    【解决方案2】:

    假设 n 是区间大小,N 是 const。

    对于每个素数 p,在可被素数整除的区间中应该有大致 (R-L) / p 个数。

    找出区间中第一个可被 p 整除的数:L' = L + (p - L % p)。

    现在如果 L' > R,则没有;否则有 1 + floor((R-L') / p)。

    示例:3、[10、20]:

    L' = 10 + 3 - 10 % 3 = 12。

    区间内可被 3 整除的数字:1 + floor((20 - 12) / 3) = 3

    注意:到目前为止,我们还没有使用 p1..pN 是素数这一事实。

    剩下的问题似乎是:如何避免多次计算可被多个素数整除的数字?示例:假设我们有 3,5 和 [10, 20],我们需要避免将 15 计算两次...

    也许我们可以使用上面的计数算法只计算 (p1*p2) 等的可除性,并相应地减少总数?如果 N ist const,这应该仍然是 const 时间。因为 p1...pN 是素数,所以它们的所有乘积都必须不同(因为任何数都不能有多个素数分解)。

    【讨论】:

    • 请注意,对于可被多个素数整除的数字,您必须更加小心。您实际上需要查看 p1...pN 的所有可能组合并正确地添加或减去它们。这称为inclusion–exclusion principle。所以你确实有一些实际的复杂性,因为你需要计算素数的power set 的数字。所以假设单个素数的计算是恒定的,你仍然有 O(2^N) 的复杂度。
    • 嗯... O(2^c) = O(1)
    • 假设 N 是一个常数,当然,但是根据 OP 的问题描述,它听起来更像是一个输入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多