所有3或5的倍数的总和低于1000在C中给出了错误的答案

项目欧拉问题:

如果我们列出10以下的所有自然数是3 or 5倍数,我们得到3, 5, 6 and 9 。 这些倍数的总和是23

求出1000以下3 or 5的所有倍数的总和。

我的C代码:

 long int x; long int y; long int z = 0; long int a = 0; long int b = 0; for(x= 0; x < 1000; x += 3) a = a + x; for(y = 0; y < 1000; y += 5) b = b + y; z = a + b; printf("%lu", z); return 0; 

但我得到266333作为输出是错误的。 我用Python检查了答案,我做对了。 我想知道我在使用C代码做错了什么。 正确答案是233168

我的Python代码:

 print(sum(x for x in range(1000) if x % 3 == 0 or x % 5 == 0)) 

有些数字可以被3和5整除,你不应该将它们加两次。 像这样的代码将给出正确的结果:

 long int x,total = 0; for(x = 0; x < 1000; ++x) { if(x % 3 == 0) total = total + x; else if(x % 5 == 0) total = total + x; } printf("%ld", total); 

在上面的代码中if else if确定如果一个数字可以被3或5整除。并允许在此基础上总结。

它可以进一步优化为:

 for(x= 0; x < 1000; ++x) { if(x%3 == 0 || x%5 == 0) total = total + x; } 

以上解决方案是O(n)以获得更好的时间复杂度O(1)我们可以使用间隔为3和5的算术级数。

在此处输入图像描述

n =给定范围(1 ... R)内给定数(Num)的倍数的总数。 在这种情况下(1 ... 1000)

a1 =第一个倍数。 这里将是3或5。

an =最后一个。 即3Xn

因此,下面的代码将计算给定范围1 ... lastOfRange(不包括lastOfRange)的间隔为3/5(Num)的系列之和。

 long SumOfSeries(long Num, long lastOfRange) { long multiplesCount = (lastOfRange-1) / Num; //(lastOfRange-1) to exlude the last number 1000 here long result = multiplesCount * (Num + (multiplesCount * Num)) / 2;//Num = a1, (multiplesCount * Num) = an. return result; } 

这可以称为:

 long N = 1000; Sum = SumOfSeries(3, N) + SumOfSeries(5, N) - SumOfSeries(3*5, N); printf("%ld", total); 

答案可以通过简单的算术计算,无需任何迭代。 许多Project Euler问题旨在让您考虑找到解决方案的聪明方法,而不仅仅是使用计算机的原始function来进行计算。

给定正整数NF ,小于NF的正倍数的数量是floor(( N -1)/ F )。 (floor( x )是不大于x的最大整数。)例如,5的小于1000的倍数是floor(999/5)= floor(199.8)= 199。

n为该倍数,floor(( N -1)/ F )。

第一个倍数是F ,最后一个倍数是nF 。 例如,对于1000和5,第一个倍数为5,最后一个倍数为199•5 = 995。

倍数是均匀间隔的,因此它们的平均值等于第一个和最后一个的平均值,因此它是( F + * n ** F *)/ 2。

乘数的总和等于它们的平均值乘以它们的数量,因此F的倍数小于N的总和是n •( F + nF )/ 2。

正如我们在其他答案和评论中看到的那样,将3的倍数和5的倍数之和相加,计算两次3和5的倍数。 我们可以通过减去这些数字的总和来纠正这个问题。 3和5之和的倍数是15的倍数。

因此,我们可以使用简单的算法计算所请求的总和,而无需任何迭代:

 #include  static long SumOfMultiples(long N, long F) { long NumberOfMultiples = (N-1) / F; long FirstMultiple = F; long LastMultiple = NumberOfMultiples * F; return NumberOfMultiples * (FirstMultiple + LastMultiple) / 2; } int main(void) { long N = 1000; long Sum = SumOfMultiples(N, 3) + SumOfMultiples(N, 5) - SumOfMultiples(N, 3*5); printf("%ld\n", Sum); } 

当您执行其他项目Euler问题时,您应该寻找类似的想法。

你在做什么是一些计算错误。 你会看到有一些常见的5和3的倍数,比如15,30,45 …所以既然你要在这两个总和中加入这些,你就会获得更高的价值。

对代码稍作修改即可。

 for(x= 0; x < 1000; x += 3) { if(x%5) { a = a + x; } } for(y = 0; y < 1000; y += 5) b = b + y; z = a + b; printf("%lu", z); 

直接翻译你的python代码:

 #include  int main(int argc, char *argv[]) { int sum = 0; for (int x = 0; x < 1000; x++) { if (x % 5 == 0 || x % 3 == 0) sum += x; } printf("%d", sum); } 

为了它的乐趣,我决定给问题一些额外的限制。

  • 循环迭代器不能获取不是多个值
  • 必须按数字顺序将数字添加到总和中。

 int sum_multiples(long int m1,long int m2,long int lim) { long int sum=0; for(long int i=m1;i((i+m2)/m2)*m2?((i+m2)/m2)*m2:((i+m1)/m1)*m1) sum+=i; return sum; } int main(int argc, char *argv[]) { printf("Total: %ld \n",sum_multiples(3,5,1000)); return 0; }