算法c求和2和5的倍数

时间:2012-11-20 00:25:04

标签: c performance algorithm

几天前,我接受了面试,他们问我如何用c语言计算所有数字2或5的倍数之和,从1到10000。我这样做了:

int mult2_5()
{
     int i, sum=0;
     for(i = 1; i <= 10000; i++)
        if(i % 2 == 0 || i % 5 == 0)
          sum += i;
     return sum;  
}

我想知道这个实现是否更快?

5 个答案:

答案 0 :(得分:5)

模数运算符效率低下。更快的实现将是这样的:

int multiply2_5(int max)
{
  int i, x2 = 0,x5 = 0,x10 = 0;

  for(i = 2; i < max; i+=2)    x2 += i;    // Store all multiples of 2   O(max/2)
  for(i = 5; i < max; i+=5)    x5 += i;    //  Store all multiples of 3  O(max/5)
  for(i = 10; i < max; i+=10)  x10 += i;   //   Store all multiples 10;  O(max/10)

  return x2+x5-x10;
}

在这个解决方案中,我不得不取10的倍数,因为2和5有10作为多个所以在第二个循环中它将加上已经在第一个循环中添加的10的倍数;三个循环组合有O(最大8/10)。

另一种更好的解决方案是采用数学方法。

你试图将这样的所有数字相加2 + 4 + 6 + 8 ... 10000和5 + 10 + 15 +20 + ... 10000这是2 *(1 + 2 + 3)相同+ 4 + ... + 5000)和5 *(1 + 2 + 3 + 4 + ... + 2000),'n'自然数之和为(n *(n + 1))(source )所以你可以在一个恒定的时间内计算,如下:

int multiply2_5(int max)
{
    // x = 2 + 4 + 6 + ... = 2 * (1 + 2 + 3 +...)
    // y = 5 + 10 + 15 + ... = 5 * (1 + 2 + 3 +...)
    // The sun of n natural numbers is sn = (n (n + 1)) / 2
   int x2 = max/ 2;                      // 2 * ( 1 +2 + 3 … max/2)
   int x5 = max /5;                      // 5 * ( 1 +2 + 3 … max/5)
   int x10 = max/ 10;                  
   int sn2 = 0.5 * (x2 * (x2+1));        // (n * (n + 1)) / 2
   int sn5 = 0.5 * (x5 * (x5+1)); 
   int sn10 = 0.5 * (x10 * (x10+1));
   return (2*sn2) + (5 *sn5) - (10*sn10);
}

答案 1 :(得分:2)

如果你的意思是“更快”,那么首先在纸上做好。

$ 2 \ sum_ {1&lt; = 2k&lt; = 10000} k + 5 \ sum_ {1&lt; = 5k&lt; = 10000} - 10 \ sum_ {1&lt; = 10k&lt; = 10000} k $

对不起,我的SO等式很弱......无论如何,这条路线会给你几乎可以在纸上处理的东西:减少几步后的5000 * 6001

int
mult2_5(void)
{
    return 5000*6001;
}

Project Euler problem 1非常相似。有很多人将他们的解决方案发布到这个。

答案 2 :(得分:2)

正如前面的回答中所提到的,显式循环相关的倍数比测试剩余的每个循环要好。但是没有必要计算10的倍数并减去。从5开始,逐步10,一起跳过它们。

int multiply2_5b(int max)
{
  int i, x2 = 0,x5 = 0;

  for (i = 2; i < max; i += 2)    x2 += i;    // Sum all multiples of 2   
  for (i = 5; i < max; i += 10)   x5 += i;    // Sum all odd multiples of 5

  return x2 + x5;
}

答案 3 :(得分:1)

这可以用数学来完成。像2 * sum(1 to 5000) + 5 * sum(1 to 2000) - 10 * sum(1 to 1000).一样的错误就像运动一样。

答案 4 :(得分:0)

我几乎完成了一个纯粹而简单的乘法,做一个简单的循环,以35(2 + 4 + 5 + 6 + 8 + 10之和)开始,步长为60,这就是你的结果会增加多少当你拿下一批时,例如(+ i = 35; i <5976; i = i + 60){sum = sum + i} 12 + 14 + 15 + 16 + 18 + 20等 5976来自5975,是以1000结尾的最后一行数字,即992 + 994 + 995 + 996 + 998 + 1000。 事实证明,这个循环运行了100次,第一次转弯时总和增加了35次,剩余的99次增加了60次。现在可以简化为简单乘法等。