Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 求一组素数乘积的算法,顺序大于x_Algorithm_Primes_Number Theory_Hamming Numbers_Smooth Numbers - Fatal编程技术网

Algorithm 求一组素数乘积的算法,顺序大于x

Algorithm 求一组素数乘积的算法,顺序大于x,algorithm,primes,number-theory,hamming-numbers,smooth-numbers,Algorithm,Primes,Number Theory,Hamming Numbers,Smooth Numbers,考虑有限集{2,3,5,…,n}。我对素数感兴趣,但这个问题可以适用于任何一组数字。我想以升序找到这些数的所有可能乘积,尤其是大于或等于某个数x的乘积。有人知道一个很好的算法吗 编辑以澄清: 输入集合中的每个因子可以使用任意次数。如果输入是{2,3,5,7},输出将是{2,3,4,5,6,7,8,9,10,12,14,15,16,18,}。当算法产生的结果大于或等于某个数字x时,该算法可以立即停止。为此,有两种算法。首先,您可以计算这些数字之间所有可能的乘积,然后对它们进行排序。虽然这似乎是一种

考虑有限集{2,3,5,…,n}。我对素数感兴趣,但这个问题可以适用于任何一组数字。我想以升序找到这些数的所有可能乘积,尤其是大于或等于某个数x的乘积。有人知道一个很好的算法吗

编辑以澄清:


输入集合中的每个因子可以使用任意次数。如果输入是{2,3,5,7},输出将是{2,3,4,5,6,7,8,9,10,12,14,15,16,18,}。当算法产生的结果大于或等于某个数字x时,该算法可以立即停止。

为此,有两种算法。首先,您可以计算这些数字之间所有可能的乘积,然后对它们进行排序。虽然这似乎是一种幼稚的方法,但您可以通过“记住”上一个产品、划分一个数字并将不同的数字相乘来加快速度。这将大大减少必要的操作数量,如果通过排列的正确顺序,可以最小化总乘法

另一方面,你能做的是计算所有原始数的集合,两个原始数对的积的集合,3的积的集合。。。等等。然后,您可以对每个单独的集合进行排序,这应该不难确保它们几乎都已排序,然后合并将集合排序到一个已排序的产品列表中。这将需要更多的操作,但最终会产生一个几乎排序的列表,这可能需要更少的时间来构建整个列表


另一种算法是取所有感兴趣的素数的乘积,并称之为p。构造另一个包含所有原始素数平方的列表。现在,将所有数循环到P,并测试它们是否可以被素数平方数组中的任何值整除。如果是的话,扔掉它们。如果没有,则将它们添加到输出数组中。您可以通过只测试sqrti的可分性来优化它,其中i是for循环中的迭代。不过,这可能仍然比上述方法慢。

为此,我们想到了两种算法。首先,您可以计算这些数字之间所有可能的乘积,然后对它们进行排序。虽然这似乎是一种幼稚的方法,但您可以通过“记住”上一个产品、划分一个数字并将不同的数字相乘来加快速度。这将大大减少必要的操作数量,如果通过排列的正确顺序,可以最小化总乘法

另一方面,你能做的是计算所有原始数的集合,两个原始数对的积的集合,3的积的集合。。。等等。然后,您可以对每个单独的集合进行排序,这应该不难确保它们几乎都已排序,然后合并将集合排序到一个已排序的产品列表中。这将需要更多的操作,但最终会产生一个几乎排序的列表,这可能需要更少的时间来构建整个列表


另一种算法是取所有感兴趣的素数的乘积,并称之为p。构造另一个包含所有原始素数平方的列表。现在,将所有数循环到P,并测试它们是否可以被素数平方数组中的任何值整除。如果是的话,扔掉它们。如果没有,则将它们添加到输出数组中。您可以通过只测试sqrti的可分性来优化它,其中i是for循环中的迭代。不过,这可能仍然比上述方法慢。

您可能还希望在输出中包含2^0*3^0*5^0*7^0=1

实现这一点的方法是使用优先级队列。如果k在序列中,那么2k、3k、5k和7k也在序列中。以1开始输出,然后将2、3、5和7添加到优先级队列中。从队列顶部弹出2,并将2*2=4、2*3=6、2*5=10和2*7=14添加到队列中;此时的队列将包含3、4、5、6、7、10和14。从队列顶部弹出3,并将3*2=6、3*3=9、3*5=15和3*7=21添加到队列中。等等

你会发现许多元素是重复的;例如,在上面的示例中,我们两次向优先级队列添加了6。您可以添加重复项,并在每次弹出队列时检查该元素是否与序列的前一个成员相同,也可以在队列中保留一个单独的项目列表,并在第一时间避免添加重复项


我将在讨论仅包含不同元素的优先级队列。

您可能还希望在输出中包含2^0*3^0*5^0*7^0=1

实现这一点的方法是使用优先级队列。如果k在序列中,那么2k、3k、5k和7k也在序列中。以1开始输出,然后将2、3、5和7添加到优先级队列中。从队列顶部弹出2,并将2*2=4、2*3=6、2*5=10和2*7=14添加到队列中;此时的队列将包含3、4、5 、6、7、10和14。从队列顶部弹出3,并将3*2=6、3*3=9、3*5=15和3*7=21添加到队列中。等等

你会发现许多元素是重复的;例如,在上面的示例中,我们两次向优先级队列添加了6。您可以添加重复项,并在每次弹出队列时检查该元素是否与序列的前一个成员相同,也可以在队列中保留一个单独的项目列表,并在第一时间避免添加重复项


我讨论一个优先级队列,它只包含不同的元素。

由于每个素数都允许出现多次,所以序列是无限的。所以我们不能生成所有产品,然后对它们进行排序。我们必须迭代地生成序列

如果a是序列的一个成员,那么{2*a,3*a,5*a…n*a}也将是序列的成员,稍后会出现

所以,我想到的算法是,为下一个序列成员提供一个排序的、无重复的缓冲区。我们提取并呈现最小值,并将其所有倍数插入缓冲区


由于很难预测起始数字x的缓冲区内容,因此该算法应从一开始就开始,忽略结果,直到它们达到x阈值。

由于每个素因子都允许多次出现,因此序列是无限的。所以我们不能生成所有产品,然后对它们进行排序。我们必须迭代地生成序列

如果a是序列的一个成员,那么{2*a,3*a,5*a…n*a}也将是序列的成员,稍后会出现

所以,我想到的算法是,为下一个序列成员提供一个排序的、无重复的缓冲区。我们提取并呈现最小值,并将其所有倍数插入缓冲区


由于很难预测起始编号x的缓冲区内容,因此此算法应从起始处开始,忽略结果,直到结果达到x阈值。

编辑:使其按升序生成所有产品;让用户随心所欲地过滤它们。这是一个普遍的问题

示例用法

 Prelude Hamming> take 10 $ dropWhile (< 1000) $ genHamming [2,3,5]
 [1000,1024,1080,1125,1152,1200,1215,1250,1280,1296]
 Prelude Hamming>

编辑:使其按升序生成所有产品;让用户随心所欲地过滤它们。这是一个普遍的问题

示例用法

 Prelude Hamming> take 10 $ dropWhile (< 1000) $ genHamming [2,3,5]
 [1000,1024,1080,1125,1152,1200,1215,1250,1280,1296]
 Prelude Hamming>

每一个大于1的整数都是一组素数的乘积,因为它是素数因子的乘积。从所需的最小数开始,划掉初始集合中没有素因子的所有数可能会更容易。继续此过程,直到结果集足够大。实际上,你是在做一个改进的埃拉托什尼筛,去掉初始集以外的所有素数的倍数。

每个大于1的整数都是“素数集”的乘积,因为它是其素数因子的乘积。从所需的最小数开始,划掉初始集合中没有素因子的所有数可能会更容易。继续此过程,直到结果集足够大。实际上,你正在做一个埃拉托斯坦的改进筛,除去初始集合中所有的素数倍数。

哈斯克尔代码,如图所示

哈姆::[Integer]->[Integer] hamm[]=[] hamm p:ps=xs-例如hamm[2,3,5] 其中xs=merge hamm ps-H{p}∪ ps=S, p:map p*xs-S⊇ {p}∪ Hps∪ {p*x | x∊ S} 合并a@x:xsb@y:ys | x ~>拿20美元哈姆[2,3,5,7] [2,3,4,5,6,7,8,9,10,12,14,15,16,18,20,21,24,25,27,28] 如果不是,则需要使用union

协会a@x:xsb@y:ys | xy=y:union a ys |否则=x:union xs ys 联合[]b=b 联合a[]=a 从上面有效地开始给定值可能是一个有趣的挑战。可以将在底部直接生成代码的切片作为起点

通常,在传递值之前,很容易沿着有序序列跳过。在Haskell中,它是通过内置dropWhile ~>在<100$hamm[2,3,5,7] [100,105,108,112,120,125,126,128,135,140] 一个Haskell代码,如图所示

哈姆::[Integer]->[Integer] hamm[]=[] hamm p:ps=xs-例如hamm[2,3,5] 其中xs=merge hamm ps-H{p}∪ ps=S, p:map p*xs-S⊇ {p}∪ Hps∪ {p*x | x∊ S} 合并a@x:xsb@y:ys | x ~>拿20美元哈姆[2,3,5,7] [2,3,4,5,6,7,8,9,10,12,14,15,16,18,20,21,24,25,27,28] 如果不是,则需要使用union

协会a@x:xsb@y:ys | xy=y:union a ys |否则=x:union xs ys 联合[]b=b 联合a[]=a 从上面有效地开始给定值可能是一个有趣的挑战。可以将在底部直接生成代码的切片作为起点

通常,在传递值之前,很容易沿着有序序列跳过。在Haskell中,它是通过内置dropWhile ~>在<100$hamm[2,3,5,7] [100,105,108,112,120,125,126,128,135,140]
因为我们的应用程序是用python编写的,所以我提出了以下实现,希望与大家分享:

def powers(x):
    y = x
    while True:
        yield y
        y *= x


def products(factors):
    y0 = factors[0]
    if len(factors) == 1:
        yield from powers(y0)
    else:
        yield y0
        g1 = products(factors)
        y1 = y0 * next(g1)
        g2 = products(factors[1:])
        y2 = next(g2)
        while True:
            if y1 < y2:
                yield y1
                y1 = y0 * next(g1)
            else:
                yield y2
                y2 = next(g2)


if __name__ == "__main__":
    import itertools
    for n in itertools.islice(products([2, 3, 5, 7]), 10**6):
        print(n)

毫无疑问,可以改进对生成器的递归使用,但在实践中,对于我们的应用程序来说,性能已经足够好了。除此之外,我仍然对如何有效地从给定的最小值开始感兴趣,如Will Ness'中所述。感谢所有做出贡献的人。

因为我们的应用程序是用python编写的,所以我提出了以下实现,希望与大家分享:

def powers(x):
    y = x
    while True:
        yield y
        y *= x


def products(factors):
    y0 = factors[0]
    if len(factors) == 1:
        yield from powers(y0)
    else:
        yield y0
        g1 = products(factors)
        y1 = y0 * next(g1)
        g2 = products(factors[1:])
        y2 = next(g2)
        while True:
            if y1 < y2:
                yield y1
                y1 = y0 * next(g1)
            else:
                yield y2
                y2 = next(g2)


if __name__ == "__main__":
    import itertools
    for n in itertools.islice(products([2, 3, 5, 7]), 10**6):
        print(n)

毫无疑问,可以改进对生成器的递归使用,但在实践中,对于我们的应用程序来说,性能已经足够好了。除此之外,我仍然对如何有效地从给定的最小值开始感兴趣,如Will Ness'中所述。感谢所有的贡献者。

你是说你想要2*2、2*3、2*5、2*n、3*3、3*5、3*n、5*5、5*n等等的结果吗?所有可能的素数乘积都是按升序排列的:。我不相信他要的序列是A00027。在我看来,理想的序列是所有可能的素数乘积的排序集。这意味着我们不能有2*2=4或2*3*3=18,因为存在重复项。为了澄清,应该包括2*2以及2*3*3和2*2*2。输入集中的每个因子都可以被使用任意次数。为什么不使用一个筛子呢?x有多大?素数集有多大?你是说你想要2*2,2*3,2*5,2*n,3*3,3*5,3*n,5*5,5*n等等的结果?所有可能的素数乘积都是升序:。我不相信他要的序列是A00027。在我看来,理想的序列是所有可能的素数乘积的排序集。这意味着我们不能有2*2=4或2*3*3=18,因为存在重复项。为了澄清,应该包括2*2以及2*3*3和2*2*2。输入集中的每个因子都可以被使用任意次数。为什么不使用一个筛子呢?x有多大?素数集有多大?优先级队列的大小为^2/3,因此会影响复杂性,这是不必要的,我曾经推导过,但现在记不起来了。这也意味着序列在队列中的^2/3个值上超过了第n个值。原来的Dijkstra算法只保留n个指针,n个给定的基素数,返回到已经生成的序列中,同样在距第n个元素^2/3的深度处;哪些指针输入优先级队列,但大小为固定的n,所以不会影响复杂性。所以就个人而言,我不喜欢这里的PQ,但当然是YMMV优先级队列的大小将为^2/3,因此将不必要地影响复杂性。我曾经推导过这个,但现在记不起来了。这也意味着序列在队列中的^2/3个值上超过了第n个值。原来的Dijkstra算法只保留n个指针,n个给定的基素数,返回到已经生成的序列中,同样在距第n个元素^2/3的深度处;哪些指针输入优先级队列,但大小为固定的n,所以不会影响复杂性。所以就个人而言,我不喜欢这里的PQ,但当然是YMMV在每个步骤上插入给定k个基素数的所有k个倍数会导致序列过多。原始的Dijkstra算法将k个指针保留回已经生成的序列中,并只将一个最小倍数插入序列中,使生成该序列的所有指针前进。下面是一个例子。在每个步骤上为给定的k个基素数插入所有k个倍数会导致序列过度生成。最初的Dijkstra算法将k个指针保留回已经生成的序列中,并只将一个最小倍数插入序列中,从而推进生成该序列的所有指针。