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
Python 在给定范围内查找倍数的加速算法_Python_Algorithm - Fatal编程技术网

Python 在给定范围内查找倍数的加速算法

Python 在给定范围内查找倍数的加速算法,python,algorithm,Python,Algorithm,如何加快我在给定范围内对倍数求和的算法,让我感到困惑。这是针对codewars.com上的一个问题,这里有一个问题的链接 这是代码,我将在底部解释发生了什么 import itertools def solution(number): return multiples(3, number) + multiples(5, number) - multiples(15, number) def multiples(m, count): l = 0 for i

如何加快我在给定范围内对倍数求和的算法,让我感到困惑。这是针对codewars.com上的一个问题,这里有一个问题的链接

这是代码,我将在底部解释发生了什么

import itertools

def solution(number):
        return multiples(3, number) +  multiples(5, number) - multiples(15, number)

def multiples(m, count):

    l = 0
    for i in itertools.count(m, m):
        if i < count:
            l += i
        else:
            break
    return l

print solution(50000000) #takes 41.8 seconds
#one of the testers takes 50000000000000000000000000000000000000000 as input

# def multiples(m, count):
#     l = 0
#     for i in xrange(m,count ,m):
#         l += i
#     return l

我的程序在得到正确答案方面没有问题。当输入较大时,问题就会出现。当输入50000000这样的数字时,返回答案需要40秒以上。我需要的输入之一是50000000000000000000000000000,这是一个巨大的数字。这也是我使用
itertools.count()
的原因。我在第一次尝试中尝试使用
xrange
,但range无法处理大于c类型long的数字。我知道问题最慢的部分是乘法方法…但是它比我第一次尝试使用列表理解和检查
I%3==0或I%5==0
,有什么想法吗?

这个解决方案对于大数应该更快

def solution(number):
    number -= 1
    a, b, c = number // 3, number // 5, number // 15
    asum, bsum, csum = a*(a+1) // 2, b*(b+1) // 2, c*(c+1) // 2
    return 3*asum + 5*bsum - 15*csum

说明:

取1到n之间的任意顺序:

1, 2, 3, 4, ..., n
它的和总是由公式
n(n+1)/2
给出。如果你认为表达式<代码>(1 +N)/2 < /COD>只是计算平均值的一个捷径,或者这个特定的数字序列,这是可以很容易证明的。因为
average(S)=sum(S)/length(S)
,如果你取任何数字序列的平均值,然后乘以序列的长度,你就得到了序列的和

如果给我们一个数字n,我们想要一些给定k到n的倍数之和,包括n,我们想要求和:

k + 2k + 3k + 4k + ... xk
其中xk是小于或等于n的k的最高倍数。现在请注意,此总和可以分解为:

k(1 + 2 + 3 + 4 + ... + x)
我们已经得到了k,所以现在我们只需要找到x。如果x被定义为可以将k乘以以获得小于或等于n的自然数的最大数,那么我们可以使用Python的整数除法获得数字x:

n // k == x
一旦我们找到x,我们就可以使用前面的公式找到任意给定k到给定n的倍数之和:

k(x(x+1)/2)
我们的三个给定k分别是3、5和15

我们发现我们的x在这一行:

a, b, c = number // 3, number // 5, number // 15
asum, bsum, csum = a*(a+1) // 2, b*(b+1) // 2, c*(c+1) // 2
return 3*asum + 5*bsum - 15*csum
在这一行中计算它们的倍数之和,直到n:

a, b, c = number // 3, number // 5, number // 15
asum, bsum, csum = a*(a+1) // 2, b*(b+1) // 2, c*(c+1) // 2
return 3*asum + 5*bsum - 15*csum
最后,用这行中的k乘以它们的总和:

a, b, c = number // 3, number // 5, number // 15
asum, bsum, csum = a*(a+1) // 2, b*(b+1) // 2, c*(c+1) // 2
return 3*asum + 5*bsum - 15*csum

我们有答案

真正的优化将是一种完全不同的方法。你不需要迭代范围内的所有数字,这个问题有一个封闭形式的解决方案。我用谷歌搜索了封闭形式,得到的定义是,“如果一个方程从一个给定的普遍接受的集合中用函数和数学运算来解决一个给定的问题,那么它就被称为闭式解。例如,无限和通常不被视为闭合形式读过之后,我仍然对封闭形式的含义感到困惑。你能告诉我吗?我的意思是,你可以想出一个简单的算术函数,给定一个数字n和一个范围r,它将给出在[0..r]范围内有多少个n的倍数的答案。我知道如何计算给定范围或数字中的倍数,我以前试过。我能够通过使用⌊b/n⌋ - ⌈a/n⌉ + 1,我在这里读到过,我不知道如何应用它,因为问题是求给定范围内所有倍数的和,例如3,6,9=18,而9中有3个倍数。你会很高兴听到还有一个计算算术序列和的封闭式公式:)解决方案成功了!您能解释一下它是如何工作的以及为什么工作得这么好吗?@msanti Related:谢谢大家!我现在明白了,哈哈,谢谢沙尚克斯的精彩解释,谢谢链接@yurib和Ashwini@msanti伟大的问题!如果需要更多解释,请告诉我。:)