代码
def tot_sum(n)
sum_of_one(n, 3) + sum_of_one(n, 5) + sum_of_one(n, 7) -
sum_of_one(n, 3*5) - sum_of_one(n, 3*7) - sum_of_one(n, 5*7) +
sum_of_one(n, 3*5*7)
end
def sum_of_one(n, m)
nbr_multiples = (n-1)/m
m * (1 + nbr_multiples) * nbr_multiples / 2
end
示例
tot_sum(120)
#=> 3951
tot_sum(1000)
#=> 271066
tot_sum(10**30)
#=> 271428571428571428571428571427928571428571428571428571428569
说明
考虑n = 120 的示例。首先将1 和119 之间可以被3 整除的整数相加:
nbr_multiples = (120 - 1)/3
#=> 39
3 * (1 + 2 + ... + nbr_multiples)
括号中的表达式等于一个代数级数的总和,所以总和等于:
3 * (1 + nbr_multiples) * nbr_multiples / 2
#=> 2340
这正是sum_of_one(120, 3)执行的计算:
sum_of_one(120, 3)
#=> 2340
同样,
sum_of_one(120, 5)
#=> 1380
sum_of_one(120, 7)
#=> 1071
这三个计算的总和是:
2340 + 1380 + 1071
#=> 4791
但是,这个总数是 3 * 5 = 15、3 * 7 = 21 和 5 * 7 = 35 的倍数。因此,我们必须从总数中减去以下各项:
sum_of_one(120, 3*5)
#=> 420
sum_of_one(120, 3*7)
#=> 315
sum_of_one(120, 5*7)
#=> 210
给我们:
4971 - 420 - 315 - 210
#=> 3846
这种调整本身会导致另一个问题,其中涉及小于120 的3*5*7 #=> 105 的倍数。这些值(实际上只有一个105)包含在sum_of_one 的所有前三个计算中,但也包含在从第一个总数中减去的所有三个调整中,净效果是它们是不包括在最后的总数中。因此,我们必须将它们重新添加:
3846 + sum_of_one(120, 3*5*7)
#=> 4026 + 105 => 3951
这等于所需的值,即小于 120 且是 3、5 或 7 倍数的正整数之和。如果事实是 tot_sum(120) 执行的计算。