从简单问题开始。——Polya
求由数字4、5和6组成的n位数的和。
正如Yu Hao上面解释的那样,这里有3**n
个数字,它们的平均值是555555,因此总和为3**n * (10**n-1)*5/9
。但如果你没有发现这一点,下面是另一种解决问题的方法。
这个问题具有递归结构,因此让我们尝试一个递归解决方案。设g(n)是所有恰好由n个数字456组成的数字的总和。然后我们有以下递推关系:
g(n) = (4+5+6)*10**(n-1)*3**(n-1) + 3*g(n-1)
要查看这个,需要将每个数字的第一位分离出来(例如,对于n=3,是百位数)。这给出了第一个术语。第二个术语是剩余数字的总和,对于前缀4、5、6的每个g(n-1)计数。
如果仍不清楚,请写出n=2的总和并将十位数与个位数分开:
g(2) = 44+45+46 + 54+55+56 + 64+65+66
= (40+50+60)*3 + 3*(4+5+6)
= (4+5+6)*10*3 + 3*g(n-1)
很好。这时候,热心的读者可能想要验证余豪的g(n)公式是否符合我们的递推关系。
为了解决OP的问题,需要计算从4到666666的所有456位数之和,即
g(1) + g(2) + g(3) + g(4) + g(5) + g(6)
。在Python中,可以使用动态规划实现:
def sum456(n):
"""Find the sum of all numbers at most n digits which consist of 4,5,6 only"""
g = [0] * (n+1)
for i in range(1,n+1):
g[i] = 15*10**(i-1)*3**(i-1) + 3*g[i-1]
print(g)
return sum(g)
当n=6时
>>> sum456(6)
[0, 15, 495, 14985, 449955, 13499865, 404999595]
418964910
编辑:我注意到原帖截断了总和,只有666554,所以它不符合一般的模式。它将少于最后几项。
>>> sum456(6) - (666555 + 666556 + 666564 + 666565 + 666566 + 666644 + 666645 + 666646 + 666654 + 666655 + 666656 + + 666664 + 666665 + 666666)
409632209