项目Euler 1:找到低于1000的3或5的所有倍数的总和,适用于10个数字但不适用于1000

时间:2017-11-16 01:38:43

标签: c# algorithm math sum

  
    
      
        

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

      
    
  

所以我决定尝试解决Euler网站上的一些问题以改进编程。在尝试解决第一个问题时,我写了一个快速代码来计算总和,它适用于10个数字,但对于1000它给我看了答案:166833这是错误的,我在这里找不到问题。如果有人可以给我一些改进我的算法的提示,那么它就会起作用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Multiplies_of_3_and_5
{
  class Program
  {
    static void Main(string[] args)
    {            
        int[] array = new int[7000];

        for (int j = 0; j<array.Length ;j++)
        {
            array[j] = j + 1;
        }

        int n = 1;
        int z = 1;
        int numbers = 0;

        for (int i = 0; i<999; i++)
        {
            if (array[i] == 3 * n )
            {
                n++;                    
                numbers += array[i];
            }

            else if (array[i] == 5 * z)
            {
                z++;
                numbers += array[i];
            }                                                           
        }
        Console.WriteLine(string.Join(" ", numbers));
        Console.ReadLine();
      }
   }
}

5 个答案:

答案 0 :(得分:3)

您应该阅读模运算符(%)。

  static void main(String[] args)
  {
    int sum = 0;
    for(int i=1; i< 1000; i++){
      if (i % 3 == 0 || i % 5 == 0){
        sum += i;
      }
    }
    Console.WriteLine(sum);
  }

为了给出解释,模运算符在对值执行整数除法时给出余数。

例如,6%3 == 0(3个均分6),7%3 == 1(7除以3,剩余1)。

因此,要将3和5的所有倍数相加,只需检查该值是否均匀地除以3或5(if语句),如果是,则将其添加到运行总和中。

请注意,当您获得3 AND 5的倍数时,您的算法将会搞砸。在这种情况下,您永远不会添加到z。您还需要将其更改为&lt; = 999,而不是&lt; 999(您的代码中永远不会添加999,除以3)。

总结一下:

  1. 直接使用循环变量,无需预先填充另一个变量 数组或具有单独的值,以跟踪您的多重 在。

  2. Modulo非常实用。

答案 1 :(得分:3)

创意计算3s,5s并扣除15s,因为它们都在两者中,但只需要计算一次。

int maxNum = 999;
int num3s = maxNum/3; // rounded down 333
int num5s = maxNum/5; // rounded down 199

int num15s = maxNum/15; // rounded down 66

知道还有多少人还没有告诉我们总和。毕达哥拉斯救援。

sum3s = 3+6+9+12+15 (=45)
sum5s = 5+10+15     (=30) 
sum15s = 15         (=15)

average =(max + min)/ 2

要么是奇数3个,5个或15个,你就得到一个平均值。或者有一个偶数,在这种情况下/ 2和偶数相互抵消。

所以我们得到

sumXs = (min+max)*numXs

在上述情况下,我们得到了

sum3s = (3+15)/2*5 = 45
sum5s = (5+15)/2*3 = 30
sum15s = (15+15)/2*1 = 15


int sum = sum3s+sum5s-sum15s = 60;

另一个例子11

sum = (3+9)/2*3 + (5+10)/2*2 - 0 = 33

最后总计3s和5s到999

sum = (3+999)/2*333 + (5+995)/2*199 - (15+990)/2*66
    = 501*333 + 500*199 - (1005)*66/2 
    = 501*333 + 500*199 - 1005*33 
    =  166833 +   99500 -   33165
    =  233168

这也是计划的结果。

答案 2 :(得分:1)

当达到15时,n会增加,但z不会增加。因此,第二个分支(“可被5分”)将不再触发。

您可以为两者使用标志,然后使用这些标志来增加数字,n和z,或者按照建议使用模数。

答案 3 :(得分:1)

Enumerable.Range(1, 999).Sum(x => x % 3 == 0 || x % 5 == 0 ? x : 0);

答案 4 :(得分:0)

在听取了你的提示后,我重新编写了我的代码,它运行得很好。但这样做肯定是一种痛苦,所以我建议使用(%)。无论如何,我也会在这里发布我的代码。再次感谢您的帮助!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Multiplies_of_3_and_5
{
  class Program
  {


    static void Main(string[] args)
    {

        int[] array = new int[7000];

        for (int j = 0; j < array.Length; j++)
        {
            array[j] = j + 1;
        }


        int n = 1;
        int z = 1;
        int numbers = 0;

        for (int i = 0; i < 999; i++)
        {

            if (array[i] == 3*n && array[i] == 5*z)
            {
                n++;
            }

            if (array[i] == 3 * n)
            {

                n++;
                numbers += array[i];
            }

            if (array[i] == 5 * z)
            {
                z++;
                numbers += array[i];
            }




        }
        Console.WriteLine(string.Join(" ", numbers));
        Console.ReadLine();

    }
  }
}