[英]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
当然有一种模式。 让我们来看看总结a
和b
之间所有奇数和偶数的数字的问题。
例如: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.