在下面的代码片段中,我找到了区间[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
有没有一种有效的方法来实现同样的目标? 任何模式,导致明确的公式。
中进行了搜索答案 0 :(得分:3)
避免转换到字符串和从字符串转换的所有开销,并直接使用数字本身:
.val()
答案 1 :(得分:2)
当然有一种模式。让我们看看在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次的所有数字之和。左边部分是7 + 8 + 9加3次1,右边是0 + 1 + 2 +的总和3加4次3。
中间部分可以包含几个十个块,例如,如果你计算17到63之间的范围,你可以得到40倍45加10个simes,其中的数字从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的评论时,我注意到可以通过编写一个函数来简化算法,将所有数字中的数字从零加到n
,然后计算差值{{1 }}。可能有更多的优化机会。