24小时热门版块排行榜    

查看: 4041  |  回复: 20
本帖产生 6 个 程序强帖 ,点击这里进行查看
当前只显示满足指定条件的回帖,点击这里查看本话题的所有回帖

holmescn

金虫 (正式写手)

[交流] Euler 工程 第五题:能被1到20所有的数都整除的最小正数 已有11人参与

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?

2520是一个能被1到10中的每个数都除尽的最小的数。
那么能被1到20所有的数的整除的最小的正数是多少呢?
回复此楼
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

holmescn

金虫 (正式写手)

★ ★ ★
余泽成(金币+3): 鼓励讨论! 2011-05-13 21:14:16
微尘、梦想(程序强帖+1): 2011-05-14 19:29:31
OK,贴算法了!

本题其实在数学上很简单,能被1到20所有的数都整除的最小正数,当然就是1到20这20个数的最小公倍数。所以用最小公倍数算法就最简单了。关于最小公倍数算法,请自行看书或查维基百科。

算法说明:
求最小公倍数,当然就是把所有合数的质因子,去掉公因子,然后再乘起来就OK了。

下面给出三种语言的实现:

Matlab:
CODE:
clear;
tic;
primes  = [2 3 5 7 11 13 17 19];
factors = [];
numbers = 1:20;

for i = 1:length(primes)
    while any(mod(numbers, primes(i)) == 0)
        for j = 1:length(numbers)
            if mod(numbers(j), primes(i)) == 0
                numbers(j) = numbers(j) / primes(i);
            end
        end
        factors = [factors primes(i)];
    end
end

result = 1;
for i = 1:length(factors)
    result = result * factors(i);
end
disp(num2str(result));
toc;

Fortran:
CODE:
Program Euler5
    Implicit None
    Integer, Dimension(8) :: Primes
    Integer, Dimension(100) :: Factors
    Integer, Dimension(20)  :: Numbers
    Integer I, J, N
    Real(8) :: Res

    Primes = (/2, 3, 5, 7, 11, 13, 17, 19/)
    Numbers = (/(I, I=1, 20)/)
    N = 1

    Do I = 1, Size(Primes)
        Do While(Any(Mod(Numbers, Primes(I)) == 0))
            Do J = 1, Size(Numbers)
                If(Mod(Numbers(J), Primes(I)) == 0) Then
                    Numbers(J) = Numbers(J) / Primes(I)
                EndIF
            EndDo
            Factors(N) = Primes(I)
            N = N + 1
        EndDo
    EndDo

    Res = 1.0
    Do I = 1, N - 1
        Print '(I2)', Factors(I)
        Res = Res * Factors(I)
    EndDo

    Print '(F20.0)', Res

EndProgram Euler5

C:
CODE:
#include

int any(int Numbers[], int n, int Prime){
    int i;
    for(i = 0; i < n; i++){
        if(Numbers[i] % Prime == 0)
            return 1;
    }

    return 0;
}

int main(int argc, char** argv){
    int Primes[] = {2, 3, 5, 7, 11, 13, 17, 19};
    int Factors[100];
    int Numbers[20];
    int sizeOfNumbers = sizeof(Numbers)/sizeof(int);
    int sizeOfPrimes  = sizeof(Primes)/sizeof(int);
    int i, j, n = 0;
    double result = 1;

    for(i = 0; i < sizeOfNumbers; i++) Numbers[i] = i + 1;

    for(i = 0; i < sizeOfPrimes; i++) {
        while(any(Numbers, sizeOfNumbers, Primes[i])) {
            for(j = 0; j < sizeOfNumbers; j++){
                if(Numbers[j] % Primes[i] == 0){
                    Numbers[j] /= Primes[i];
                }
            }
            Factors[n++] = Primes[i];
        }

    }

    for(i = 0; i < n; i++){
        result *= Factors[i];
    }
    printf("%18.0f\n", result);

    return 0;
}

当然我这里偷个个懒,就是直接给出了小于20的质数。不过,这个质数列表的生成也不难,参考Euler 工程 第三题的算法。

如果要给出N个数的最小公倍数。只要给个Numbers的列表就可以了。我想这个算法还是很实用的。

[ Last edited by holmescn on 2011-5-13 at 12:51 ]
8楼2011-05-13 11:31:07
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
查看全部 21 个回答

libralibra

至尊木虫 (著名写手)

骠骑将军

★ ★ ★ ★
小木虫(金币+0.5):给个红包,谢谢回帖
余泽成(金币+3): 鼓励交流! 2011-05-12 19:11:36
余泽成(程序强帖+1): 2011-05-12 19:12:13
CODE:
%% evenly divided by 1:20
% Elapsed time is 173.211097 seconds.
% ans =
%    232792560
function result = euler5()
tic;
flag = 0;
result = 2520; % 能被1-20整除,肯定比能被1-10整除的2520大
while flag==0
    result = result+10; % 能被10整除,所以每次增加10
    flag = ~any(mod(result,2:20)); % 检测2-20,如果全部可以整除,改变flag结束循环
end
toc;
end

效率有点低,170多秒啊,
matlab/VB/python/c++/Java写程序请发QQ邮件:790404545@qq.com
2楼2011-05-12 16:36:07
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

holmescn

金虫 (正式写手)

引用回帖:
Originally posted by libralibra at 2011-05-12 16:36:07:
[code] %% evenly divided by 1:20
% Elapsed time is 173.211097 seconds.
% ans =
%    232792560
function result = euler5()
tic;
flag = 0;
result = 2520; % 能被1-20整除,肯定比能被1-10整除的2520 ...

1. 为什么不用all,要用any呢?
2. 问题很简单啊,算法太粗暴了。
3楼2011-05-12 16:45:10
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

微尘、梦想

木虫 (知名作家)

★ ★ ★ ★
小木虫(金币+0.5):给个红包,谢谢回帖
余泽成(金币+3, 程序强帖+1): 谢谢参与交流! 2011-05-12 19:12:02
CODE:
#include
#include
int x(int i);
void main(void)
{
        int i;
        float dif;
        time_t start,end;

        time(&start);
        for(i=1;1;i++)
                if(x(i))
                {
                        printf("%d\n",i);
                        break;
                }
        time(&end);
        dif=difftime(end,start);
        printf("运算时间:%.1f秒\n",dif);
}
int x(int i)
{
        int j,k=0;
        for(j=2;j<21;j++)
                if(i%j==0)
                        k++;
        if(k==19)
                return 1;
        else return 0;
}

答案:232792560
运行时间:37s

算法:最笨的那种!

[ Last edited by 微尘、梦想 on 2011-5-12 at 17:20 ]
任风云变幻,我笑对人生!
4楼2011-05-12 17:19:14
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
普通表情 高级回复 (可上传附件)
信息提示
请填处理意见