问题:
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.
答案原文:Nice work, nicocarlos!
He is using a clever improvisation of the formulae for arithmetic progressions. For example, to find the sum of the terms 3,6,9,12,..., you would use (n/2)(a+l), where n is the number of terms, a is the first term, and l is the last term. But to find the last term requires a bit of work. The nth term is given by a+(n-1)d, where d is the common difference. So we need to solve 3+3(n-1)=1000, giving 3(n-1)=997, and n=997/3+1=333.333... However, n must be integer, so int(333.333...)=333, and checking, 3+3(333-1)=999; this is the last term before 1000.
In general, a+(n-1)d=x, gives n=int((x-a)/d+1).
But for this problem we can improve even further, as a=d we get n=int(x/d-d/d+1)=int(x/d).
The nth (last) term, l=a+(n-1)d=d+(int(x/d)-1)*d=d*int(x/d).
Combining this to find the sum, S=(n/2)(a+l)=(int(x/d)/2)*(d+d*int(x/d)).
Simplifying, S=d*int(x/d)*(1+int(x/d))/2.
As the problem asks for the sum of multiples of 3 and 5 we find the sum of each series, but as 3,6,9,... and 5,10,15,... have multiples of 15 in common, we need to subtract the series for 15,30,45,...
However, caution is needed. The problem states below then 1000, so we must use 999 in the formula (otherwise it would include 1000 in the sum, as a multiple of 5):
T = 3*int(999/3)*(1+int(999/3))/2 + 5*int(999/5)*(1+int(999/5))/2 - 15*int(999/15)*(1+int(999/15))/2
Therefore, T = 3*333*(1+333)/2 + 5*199*(1+199)/2 - 15*66*(1+66)/2 = 233168.
Tue, 27 Jul 2004, 18:37 euler![]() |
计算1到1000中可以被3和5整除的数的和(之后会简化为求可以被3整除的数的和),拿到问题之后我随手就写了一个for循环
long starTime = new Date().getTime();
long sum = 0;
for(int i = 0; i < 1000; i++){
if(i % 3 == 0){
sum += i;
}
}
System.out.println(sum);
System.out.println(new Date().getTime() - starTime);
运行,用时0ms,非常好,数大一点会多久呢。带着这样的问题我又把1000换成了int的最大值long starTime = new Date().getTime();
long sum = 0;
for(int i = 0; i < Integer.MAX_VALUE; i++){
if(i % 3 == 0/* || i % 5 == 0*/){
sum += i;
}
}
System.out.println(sum);
System.out.println(new Date().getTime() - starTime);
运行,3647ms好像也还可以。
后来无意间看到了这篇文章,测试一下
long starTime = new Date().getTime();
long d = 3;
long x = Integer.MAX_VALUE;
long sum = d * (int)(x / d) * (1 + (int)(x / d)) / 2;
System.out.println(sum);
System.out.println(new Date().getTime() - starTime);
运行,用时0ms。
其中运用到的只有两个简单的数学公式
s = (n / 2) * (a + l)
l = a + (n - 1) * d
其中,s为和;n为所求总数,此问题中即为int的最大值;a为起始值;l为最后一个值;d为间隔;此问题中a = d = 3
计算过程什么的我就不写了,原文中已经写的很明白了
总之重点就是关于数学对代码的影响吧