Problem 1 : Multiples of 3 and 5

逛知乎的时候发现的一个网站——projecteuler.net,蛮有意思的一个解题网站,和平常的OJ网站不太一样,只需要提交结果就好了。可以在作工作闲暇之余,练练手。
在这里提交解题过程,一是为了做笔记,二是为了督促自己。
最近正好在学python,就用python解题了。
废话完毕,开始第一题:
 

Problem:

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3,5,6 and 9.The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
 
和各大OJ网站一样,第一题通常都很简短(题目描述也很简短,英语渣渣的我居然看懂了)。
求小于1000,且能被3或5整除的所有数之和。
 
一个循环+一个分支解决,代码如下:
1 #promble 1: Multiples of 3 and 5
2 RANGE = 1000
3 sum = 0
4 num = 3
5 while num < RANGE:
6     if num % 3 == 0 or num % 5 == 0:
7         sum += num
8     num += 1
9 print(sum)
 
但是如果题目把范围扩大一点,例如10000000000。这个时候,如果用C或JAVA解题,已经无法得到正确答案了,因为int的范围为-2147483648~2147483647,sum或num都会在运算过程中溢出。python虽然还能得到正确结果,但需要相当长的一段时间等待(我等了3分钟还没出结果)。
 
进一步分析题目,以小于100的范围为例子,能被3整除的数如下:
3,6,9,12,15,……,96,99
能被5整除的数如下:
5,10,15,20,……,90,95
 
很明显是两个等差数列,可以通过数列的求和公式直接算计出结果,不需要循环累加计算。
被3整除的数列和为:
sum3of100 = 3 + 6 + …… + 96 + 99 = 3 * (1 + 2 + 3 + …… + 33) = 3 * (1 + 33) * 33  / 2
sum5of100 = 5 + 10 + …… + 90 + 95 = 5 *(1 + 2 + 3 + ……+19) = 5 * (1 + 19) * 19 / 2
当范围为小于n时,能被3整除的个数为 n / 3(整除),同理,被5整除的个数为n / 5,那通用的求和公式为:
sum3ofn  = 3 * (1 + n / 3) * (n / 3) / 2
sum5ofn = 5 * (1 + n / 5) * (n / 5) / 2
当结过并不是sum3ofn + sum5ofn。
对比两个数列可以发现,能15整除的数在两个数列里都出现了,所以正确的结果应该为:
sum3ofn + sum5ofn - sum15ofn
代码如下:
1 #promble 1: Multiples of 3 and 5
2 #计算小于target,且能被n整除的数之和
3 def sumDivisibleBy(target, n):
4     p = target // n
5     return n * p * (p + 1) / 2
6 TARGET = 10000000000 - 1
7 result = sumDivisibleBy(TARGET, 3) + sumDivisibleBy(TARGET, 5) 
8          - sumDivisibleBy(TARGET, 15)
9 print(int(result))



原文地址:https://www.cnblogs.com/foundkey/p/6065208.html