繁体   English   中英

查找整个序列的数字总和的有效方法

[英]Efficient way to find sum of digits of an entire sequence

在下面的代码片段中,我找到了区间[a,b]之间所有奇数的位数之和

def SumOfDigits(a, b):
    s = 0
    if a%2 == 0:
        a+=1
    if b%2 == 0:
        b-=1   
    for k in range(a,b+1,2):
        s+= sum(int(i) for i in list(str(k)))
    return s

有没有一种有效的方法来实现同样的目标? 任何图案,这导致明确的公式。

我在https://oeis.org上搜索过

避免转换到字符串和从字符串转换的所有开销,并直接使用数字本身:

def SumOfDigits(a, b):
    result = 0
    for i in range(a + (not a % 2), b + 1, 2):
        while i:
            result += i % 10
            i //= 10
    return result

当然有一种模式。 让我们来看看总结ab之间所有奇数和偶数的数字的问题。

例如:17到33

17  18  19    20  21  22  23  24  25  26  27  28  29    30  31  32  33

中间部分为您提供从0到9(45)加10次的所有数字的总和2.左侧部分是7 + 8 + 9加3次1,右侧是0 + 1 + 2 + 3加4的总和次3。

中间部分可以包含几个十个块,例如,如果你计算17到63之间的范围,你可以得到40倍45加10个simes,其中digitums从2到5。

这给你一个递归算法:

def ssum(n):
    return n * (n + 1) // 2

def dsum(a, b):
    res = 0

    if a == b:
        while a:
            res += a % 10
            a //= 10

    elif a < b:
        aa = a // 10
        bb = b // 10

        ra = a % 10
        rb = b % 10

        if aa == bb:
            res += ssum(rb) - ssum(ra - 1)
            res += (rb - ra + 1) * dsum(aa, bb)

        else:
            if ra > 0:
                res += 45 - ssum(ra - 1)
                res += (10 - ra) * dsum(aa, aa)
                aa += 1

            if rb < 9:
                res += ssum(rb)
                res += (rb + 1) * dsum(bb, bb)
                bb -= 1

            if aa <= bb:
                res += 45 * (bb - aa + 1)
                res += 10 * dsum(aa, bb) 

    return res

现在让我们将其扩展为仅包含奇数。 Adkust a ,它是偶数和b所以它是奇怪的。 你的数字和的总和现在在偶数和奇数对上运行,其中even + 1 == odd 这意味着奇数的数字id比偶数更多,因为除了最后的数字之外的所有数字都是相同的,并且最后的奇数数字比偶数数字多一个。

因此:

dsum(a, b) == oddsum + evensum

和:

oddsum - evensum == (b - a + 1) // 2

然后,将所有奇数的位数相加的函数为:

def oddsum(a, b):
    if a % 2: a -= 1
    if b % 2 == 0: b -= 1

    d = (b - a + 1) // 2

    return (dsum(a, b) + d) // 2

当我查看你关于OEIS的评论时,我注意到可以通过编写一个函数来简化算法,将所有数字中的数字从0加到n ,然后计算差值dsum(b) - dsum(a) 可能有更多的优化机会。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM