当前位置: 首页 > 知识库问答 >
问题:

投影Euler#5(可被1到20的所有数字整除的最小正数):优化方法~Java语言

越飞鸾
2023-03-14

问题5:2520是可以被1到10的每个数字除的最小数,没有任何余数。可以被1到20的所有数字整除的最小正数是多少?

我已经解决了Euler项目的问题5

以下是Java代码:

 static long FindLcm(long a,long b)
 {
     long lcm,hcf = 0;
     long i=1;
     long ger=a>b?a:b;
     while(i<ger)
     {
         if((a%i==0) && (b%i==0))
             hcf=i;
         i++;
     }
     lcm=(a*b)/hcf;
     return lcm;
 }
 static void FindMultiple()
 {
     long lcm=1;
     for(long i=2;i<=20;i++)
     {
         lcm=FindLcm(lcm,i);
     }   
     System.out.println("Lcm="+lcm);
 }

如何优化这个?

共有3个答案

水渊
2023-03-14

我就是这样做的,这是我能想到的最简单的方法。它也比你的快一点。

    for(int i = 190; ; i += 190) {
        if(i % 3 == 0 
                && i % 4 == 0
                && i % 6 == 0 
                && i % 7 == 0
                && i % 8 == 0 
                && i % 9 == 0
                && i % 11 == 0
                && i % 12 == 0 
                && i % 13 == 0 
                && i % 14 == 0 
                && i % 15 == 0
                && i % 16 == 0
                && i % 17 == 0
                && i % 18 == 0
                && i % 20 == 0) {
            System.out.println(i);
            break;
        }
    }
马阳晖
2023-03-14

你们的解决方案或多或少是蛮力,这就是为什么要花这么长时间。我们知道2520是(1,2,…,9,10)的lcm,这意味着两件有用的事情:1。)我们可以从11和2开始检查系数。)答案是2520的倍数。

您正在搜索答案的最大公约数(gcd)和序列中的下一个数字(类似于气泡排序)。您可以检查当前答案是否可以被下一个因子整除,如果不能,则将当前答案添加到自身,直到答案可以被下一个因子整除。例如:

    static long findLCM(long a, long b) {
        long lcm = (a>b) ? a : b;
        while (lcm % b != 0) {
            lcm += a;
        }
        return lcm;
    }

因为我们从lcm=a开始,我们知道只要我们将a添加到lcm,那么lcm总是可以被a整除。现在,我们只需要使a的一些倍数可以被b整除。这个过程应该省去许多首先找到gcd以及从2到10迭代的步骤。

洪弘毅
2023-03-14

你的FindMultiple()方法不错,

static void FindMultiple()
{
    long lcm=1;
    for(long i=2;i<=20;i++)
    {
        lcm=FindLcm(lcm,i);
    }
    System.out.println("Lcm="+lcm);
}

它实现了一个相当好的算法。您的问题是,您的FindLcm()包含一个严重的性能缺陷。

static long FindLcm(long a,long b)
{
    long lcm,hcf = 0;
    long i=1;
    // This sets ger to max(a,b) - why?
    long ger=a>b?a:b;
    // This would return a wrong result if a == b
    // that never happens here, though
    while(i<ger)
    {
        if((a%i==0) && (b%i==0))
            hcf=i;
        i++;
    }
    lcm=(a*b)/hcf;
    return lcm;
}

您正在循环,直到到达两个参数中较大的一个。由于累积LCM增长相当快,这需要很多时间。但是两个(正)数的GCD(或HCF,如果您愿意)不能大于两个(正)数中较小的一个。因此,仅循环到两个参数中较小的一个为止,使得迭代次数最多为20次,在这里进行19次(对于i=2,...,20),这是一个微不足道的计算量。

更改为

long ger = a < b ? a : b;
while(i <= ger) {

给我(添加计时代码,而不是测量打印):

17705 nanoseconds
Lcm=232792560

因此计算不到20微秒。如果我们使用欧几里得算法来寻找最大公约数,我们可以很容易地将其推到6微秒以下,

static long gcd(long a, long b) {
    while(b > 0) {
        a %= b;
        if (a == 0) return b;
        b %= a;
    }
    return a;
}

如果我们直接使用GCD作为

lcm *= i/gcd(lcm,i);

Find多种()中。

 类似资料:
  • 我试图找到一个最小的正数,它可以被1到20的所有数字整除。我们得到,2520是可以被1到10的每个数字除的最小数,没有任何余数。My find()查找从2520开始的数字,该数字可以被1-20之间的所有数字整除,但由于某种原因返回2520。我找不到我的find()有什么问题?

  • 求可被1到N的所有数整除的最小数,不留余数。由于数字可能非常大,我们取模100000007的答案。 我认为可以被从1到N的所有数字整除的最小数字是LCM(1... N)。 例如:对于N=5,最小值为60。 因为60是能被所有数字形式(1-5)整除的最小数。 但由于一些奇怪的原因,它给了我错误的答案大N(1000),等等。什么可以导致这里可能的错误,我在这里的登录正确吗? 这是我试图实现的。

  • 我一直在努力解决Euler项目中的第5个问题,这就像 2520是可以被1到10中的每一个数字除以而没有任何余数的最小数字。 可以被1到20的所有数字整除的最小正数是多少? 我决定更进一步,我决定找到一个最小的正数,它可以被从1到limit的所有数字平均整除,limit是用户定义的。 当我执行程序时,问题开始出现,它立即打印出0。我试图追踪我的代码,但没有成功。

  • 我正试图找出如何计算两个int(a和b)之间的所有数字,其中所有数字都可以与另一个int(k)整除,0作为除数。这是我到目前为止所做的,但它永远都是循环的。 此外,我还考虑通过计数这些数字并与位数进行比较来比较是否所有的数字都是可整除的 如有任何帮助,不胜感激。谢谢!

  • 问题内容: 我有一个程序,该程序读取两个实数,然后打印出这两个之间的所有数字,这些数字可以被2或3或5整除。该程序可以正常工作,但是当用户输入两个非常大的数字时(例如1122222123333)和214123324434434),程序需要很长时间才能计算出结果。我想以某种方式修复该程序,以便即使对于大量结果也将立即打印出来。 到目前为止,这是我的代码: 问题答案: 好吧,您根本不需要循环。 您知道

  • 昨天面试了一家公式,面试上来问我,使用过哪些STL容器,我说了一下,然后又问从最简单的开始说。 面试官:说说使用vector是需要注意什么? 我:注意什么......。迭代器失效问题。 面试官:你是看面经的吧 我:我没有看面经,平时就刷题用用这些容器,使用时需要注意什么,使用时需要注意什么(我连说两遍),平时就是用,没注意到有什么。 面试官:好吧,有看过STL源码剖析吗? 我:内心:我刷过侯捷老师