[英]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.