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))