您的位置:首页 > 其它

[Project Euler]加入欧拉 Problem 5

2011-01-27 10:47 260 查看
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-N中间所有的素数,放入数列a
中,a
不足的部分使用1来填充。

求出所有素数相乘的积。然后对剩下1-N中除去素数剩下的数,进行一次快速的删选。用这个乘积去%剩下的数种每个一个数,如果可以除尽,那剔除这个数。不能除尽保留。

对于保留的数,进行因素拆分,比如像16 = 2*2*2*2. 拆分的数对比那个素数数列a
。找出比如16里面有的,a
里面没有的部分。比如16 里面的第一个2,a
里也有,则16和数列同时剔除2,然后第二个2,a
里面已经剔除过2了,没有2了,则把这个2,加入到a
中。

依次对每个剩下的数进行如此处理。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#define N 20

bool isPrime(int n); //判断一个数是不是质数
void splitNum(int arr
, int num); // 拆分一个数为对应质数相乘的积

int main(int argc, char *argv[])
{
int num = N;
int arr
; //arr保存1-num范围内的所有质数
int arr1
; // 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
; // 拷贝质数数组数据
for(j = 0; j< pnum; j++)
copyArr[j] = arr[j];

int tmp
, 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
, 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++;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: