Multiples of 3 and 5

问题:

     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
England


    计算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

计算过程什么的我就不写了,原文中已经写的很明白了

总之重点就是关于数学对代码的影响吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值