[Project Euler]加入欧拉 Problem 5

2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.

What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?

找出最小的能够除尽1-20中间所有的数的正数。

 

这个题,我就是使用传说中的笔算,算出来的O(∩_∩)O哈哈~

首先看下能够除尽1-10中间所有的数 2520

然后分析下11-20中间所有的数

11, 12, 13, 14, 15 , 16 , 17 , 18 ,19, 20

第一步可以挑选出质数,质数肯定是不能分解的。那我们要找的数就是2520 * 11 * 13 * 17 * 19的倍数

第二步, 看下 12 = 2*6

14  = 2*7

15 = 3*5

16 = 2*2*2*2

18 = 2*3*3

20 = 2*5*2

也就是说新的数肯定不用考虑 14 15 了,因为2520里面已经包含了这个因子, 剩下需要考虑16 18 20 这3个

第三部, 我们可以看下2520 肯定可以被9 整除,同时 它也是2的倍数,故排除18,同理20.剩下需要处理16.

第四步,用2520除以16就发现只余下0.5,这样可以乘以最小的因子,也就是2 就可以满足了。

那样那个数就是

2520 * 11 * 13 * 17 * 19 * 2

哈哈。下面给出如何用计算机程序来解决这个问题吧

 

先说下使用计算机解决的思想:(使用比较简单的数组来解决)

找出能够整除1-N中间所有数的最小数

  1. 找出1-N中间所有的素数,放入数列a[N]中,a[N]不足的部分使用1来填充。
  2. 求出所有素数相乘的积。然后对剩下1-N中除去素数剩下的数,进行一次快速的删选。用这个乘积去%剩下的数种每个一个数,如果可以除尽,那剔除这个数。不能除尽保留。
  3. 对于保留的数,进行因素拆分,比如像16 = 2*2*2*2. 拆分的数对比那个素数数列a[N]。找出比如16里面有的,a[N]里面没有的部分。比如16 里面的第一个2,a[n]里也有,则16和数列同时剔除2,然后第二个2,a[N]里面已经剔除过2了,没有2了,则把这个2,加入到a[N]中。
  4. 依次对每个剩下的数进行如此处理。
#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>

#include <math.h>

#define N 20



bool isPrime(int n); //判断一个数是不是质数 

void splitNum(int arr[N], int num); // 拆分一个数为对应质数相乘的积 



int main(int argc, char *argv[])

{

    int num = N;

    int arr[N]; //arr保存1-num范围内的所有质数 

    int arr1[N]; // arr1保存1-num范围内的所有数     

    int pnum = 0;

    int i = 0;

    

    for(i = 0; i < N; i++)// 初始化arr1数组 

    arr1[i] = i + 1;

    

    for(i = 2 ; i <= num; i++) //找出1- num 范围内的所有质数 加入到整形数组中

    {

        if(isPrime(i))

        {

            arr[pnum] = i;

            pnum ++;

        }

    }

    

    unsigned long tmppro = 1; // 求出1-num范围内所有质数的乘积,进行第一次初选

    int j = 0;

    for(j = 0; j < pnum; j++)

    tmppro *= arr[j];

    for(i = 0; i < N; i++)

    {

        if(tmppro % arr1[i] == 0)

        arr1[i] = 1;

    }    

                  

    for(i = 0; i < N; i++) // 处理 1-num范围内除去质数,以及可以被整除的数,剩下的数 

    {

        if(arr1[i] != 1)

        {            

            int copyArr[N]; // 拷贝质数数组数据 

            for(j = 0; j< pnum; j++)

            copyArr[j] = arr[j];

            

            int tmp[N], k;                        

            splitNum(tmp, arr1[i]); //分拆这个数,因子保存到tmp数组里

            

            for(j = 0; j < N; j++)

            {

                if(tmp[j] != 1) // 分析每个因子 

                {

                    for(k = 0; k < pnum; k++) // 检测temp[j]是否在copyArr[j]中 

                    {

                        if(copyArr[k] == tmp[j])

                        {

                            copyArr[k] = 1;  

                            tmp[j] = 1;

                        }                                              

                    }               

                }

            }

            

            for(j = 0; j< N; j++)

            {

                if(tmp[j] != 1)

                {

                    tmppro *= tmp[j];

                    arr[pnum] = tmp[j];

                    pnum ++;

                }

            }

        }

    }

    

    printf("%lu", tmppro);

     

  

  system("PAUSE");	

  return 0;

}



bool isPrime(int n)

{

    int sqr = (int)sqrt(n + 1);

    int i;

    for(i = 2; i <= sqr; i++)

    {

        if(n % i == 0)

        return false;

    }    

    return true;    

}



void splitNum(int arr[N], int num)

{

    int i;

    

    for(i = 0; i < N; i++) // 将数组的每个元素初始化为1 

    arr[i] = 1;



    int k = 2; // 从最小的质数2进行拆分

    i = 0;

    while(k <= num)

    {

        if(num % k == 0)

        {

            arr[i] = k;

            i++;

            num = num / k;

        }

        else

        k++;

    }

}

你可能感兴趣的:(project)