【问题标题】:Given a number N and an array A. Check if N can be expressed as a product of one or more array elements给定一个数 N 和一个数组 A。检查 N 是否可以表示为一个或多个数组元素的乘积
【发布时间】:2019-07-01 16:53:00
【问题描述】:

给定一个数字N (where N <= 10^18) 和一个数组A(consisting of at most 20 elements)。我必须判断是否可以通过将数组的某些元素相乘来形成N。请注意,我可以多次使用任何元素。

示例:N = 8A = {2, 3}。在这里,8 = 2 * 2 * 2。所以答案是YES。但是如果N = 15,那么我不能将 15 形成为一个或多个元素的乘积,使用它们任意次数。所以在这种情况下,答案是NO

我该如何解决这个问题?

【问题讨论】:

  • 首先将 N 除以 A 的每个元素。如果 A 的一个元素不能均匀地划分为 N,那么您可以丢弃该元素。考虑N = 15A = {2, 3}。由于 2 不均分为 15,所以可以丢弃。
  • @user3386109 如果 N = 12 且 A = {2, 6}。在这种情况下,您的方法显示错误的答案。
  • @YaseenMollik 您的评论毫无意义。所有不是N 的除数的数字都可以从A 中删除而不影响答案。 N = 12A = {2,6} 不是那个相对明显的点的反例。在这种情况下,不会从 A 中删除任何内容
  • 这最好被认为是一个预处理步骤。在您执行任何其他操作之前,请将 A 修剪为您可以实际使用的集合。
  • 对此有一个经典的算法解决方案。您可以为数组中存在的每个元素创建队列并继续填充它们,直到找到您的元素。搜索此问题的解决方案,您的问题的方法也应相同:Find kth multiple of given numbers. For eg, if numbers are 2,3,4,5 then find 6th number divisible by all 2,3,4,5 如果您无法解决,请告诉我。

标签: algorithm math


【解决方案1】:

简单伪代码:

A_divisors = set()
for x in A:
    if num % x == 0:
        A_divisors.add(x)

candidates = A_divisors.clone()
seen = set()

while(candidates.size()):
    size = divisors.size()
    new_candidates = set()
    for y in candidates:
        for x in A_divisors:
            if num % (x * y) == 0 and (x * y) not in seen:
                new_candidates.add(x * y)
                seen.add(x * y)
            if x * y == num:
                return true
    candidates = new_candidates

return false

复杂度:O(|A| * k * log k),其中 k 是除数的数量。 log k 将是添加和检查元素是否存在于集合中的成本。使用基于散列的方法,它将是 O(1) 并且可以被删除。我还假设 %, * 操作为 O(1)。

【讨论】:

【解决方案2】:

由于您没有显示代码或算法,我只提供一个想法。如果您需要更多帮助,请展示您在该问题上的更多工作。

请注意,N 最多可以是 60 位长。这足够小,N 可以很快分解为其主要因素。所以首先要为这种大小的数字设计一个好的分解算法。

您的算法将考虑 N 和数组中的每个元素 A。如果N 的任何素因数不分成A 的任何元素,那么您的答案是NO。在您的N = 15 示例中就是这种情况。

现在您可以使用NA 的元素中的质因数及其指数。现在你想找到A 的一个子集(或更准确地说,是一个子多集),其中每个素数的指数加起来就是N 中的指数。这大大减少了数字的大小,从而使问题变得更容易。

最后一部分不是微不足道的。在这个问题上做更多工作并向我们展示你的一些工作,然后我们可以继续帮助你。

【讨论】:

  • 很好的答案 (+1) ——但您不是在寻找 A子集,而是在寻找子多重集。稍微不同的观点:给定N 的因式分解和A 的元素,用指数向量替换每个数字(包括零作为缺失素因数的位置标记)。那么问题就是将目标向量表示为其他向量的线性组合,使用非负整数作为系数。
  • @JohnColeman:你对多重集的看法是正确的——我应该使用这个术语。我会尽快改变它以使其更加清晰。我确实考虑过向量,但在提问者展示了更多他自己的工作之后,我将其保留了下来。对于需要提问者更多展示的问题,我仍在努力保持平衡,但我认为将向量留到以后对我来说是一个不错的选择。
  • 很难在给出有用的提示和为他们做作业之间取得平衡,尤其是在这种问题相当有趣的情况下。
【解决方案3】:

您可以按照以下方法:

  1. Form 2 队列:Q2Q3
  2. Q2 中添加2,在Q3 中添加3。
  3. 获取两个队列头部的最小值,比如说h。从对应的队列中移除h。检查它是否等于数字N。如果是,则返回 true。如果大于N,则返回false。
  4. 如果小于N,则在Q2中添加2*h,在Q3中添加3*h。重复步骤 3 到 4。

请注意,当最小h 来自Q3 时,您无需将2*h 添加到Q2 中。那是因为您之前已经在Q3 中添加了该元素。 (我会留给你推论}。继续这个过程,直到你的h大于N

如果你有更多这样的号码,你也可以在那里排队。如果您需要处理更多数字,我认为这是一个最佳解决方案。

你能猜出它的时间和空间复杂度吗?

【讨论】:

    猜你喜欢
    • 2021-09-06
    • 1970-01-01
    • 1970-01-01
    • 2019-09-19
    • 1970-01-01
    • 2017-01-12
    • 2021-12-20
    • 2018-07-15
    • 1970-01-01
    相关资源
    最近更新 更多