项目Euler#5(可被1到20的所有数字整除的最小正数):优化方法~JAVA

项目Euler#5(可被1到20的所有数字整除的最小正数):优化方法~JAVA,java,optimization,lcm,Java,Optimization,Lcm,问题5:2520是最小的数字,可以被1到10的每个数字除,没有余数。 能被1到20的所有数整除的最小正数是多少 我已经解决了第五道题 以下是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))

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

我已经解决了第五道题

以下是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);
 }
静态长FindLcm(长a、长b)
{
长lcm,hcf=0;
长i=1;
长ger=a>b?a:b;

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

    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;
        }
    }

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

    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;
        }
    }

你的解决方案或多或少是蛮力,这就是为什么它需要这么长时间。我们知道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开始,我们知道只要我们在lcm中加上a,那么lcm总是可以被a整除。现在,我们只需要让a的倍数可以被b整除。这个过程应该省去了首先找到gcd的许多步骤,以及从2到10的迭代。

你的解决方案或多或少是蛮力的,这就是为什么它如此花了这么长时间。我们知道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迭代的许多步骤。

你的
FindMultiple()
方法不错

static void FindMultiple()
{
    long lcm=1;
    for(long i=2;i<=20;i++)
    {
        lcm=FindLcm(lcm,i);
    }
    System.out.println("Lcm="+lcm);
}
您正在循环,直到达到两个参数中的较大值。由于累积LCM增长相当快,这需要很多时间。但是GCD(或HCF,如果您愿意)为两个(正)数字不能大于两个参数中较小的一个。因此,只有在达到两个参数中较小的一个之前循环,这里的迭代次数最多为20次,这样做19次(对于
i=2,…,20
),计算量很小

改为

long ger = a < b ? a : b;
while(i <= ger) {
因此,计算时间不到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);
FindMultiple()

中,您的
FindMultiple()
方法不错

static void FindMultiple()
{
    long lcm=1;
    for(long i=2;i<=20;i++)
    {
        lcm=FindLcm(lcm,i);
    }
    System.out.println("Lcm="+lcm);
}
您正在循环,直到达到两个参数中的较大值。由于累积LCM增长相当快,这需要很多时间。但是GCD(或HCF,如果您愿意)为两个(正)数字不能大于两个参数中较小的一个。因此,只有在达到两个参数中较小的一个之前循环,这里的迭代次数最多为20次,这样做19次(对于
i=2,…,20
),计算量很小

改为

long ger = a < b ? a : b;
while(i <= ger) {
因此,计算时间不到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);

FindMultiple()

C++程序中,迭代次数最少…非常类似于Daniel Fischer

#include<iostream>

using namespace std;

int main()
{
    int num = 20;
    long lcm = 1L;
    for (int i = 2; i <= num; i++)
    {
        int hcf = 1;
        for (int j = 2; j <= i; j++)
        {
            if (i % j == 0 && lcm % j == 0)
            {
                hcf = j;
            }
        }
        lcm = (lcm * i) / hcf;
    }
    cout << lcm << "\n";
}
#包括
使用名称空间std;
int main()
{
int num=20;
长lcm=1L;

对于(int i=2;iC++程序,具有最小迭代次数…非常类似于Daniel Fischer

#include<iostream>

using namespace std;

int main()
{
    int num = 20;
    long lcm = 1L;
    for (int i = 2; i <= num; i++)
    {
        int hcf = 1;
        for (int j = 2; j <= i; j++)
        {
            if (i % j == 0 && lcm % j == 0)
            {
                hcf = j;
            }
        }
        lcm = (lcm * i) / hcf;
    }
    cout << lcm << "\n";
}
#包括
使用名称空间std;
int main()
{
int num=20;
长lcm=1L;

对于(inti=2;i非暴力方法

这是即时的!不需要一秒钟。运行代码来理解逻辑。它是用C编写的

#include <stdio.h>

int main()  {

int primes[8]={2,3,5,7,11,13,17,19};
int primes_count[8]={0,0,0,0,0,0,0,0};
int i,j,num,prime_point;
int largest_num=1;

printf("\nNUM");
for(j=0;j<8;j++)
    printf("\t%d",primes[j]);

for(i=2;i<=20;i++)  {
    num=i;
    int primes_count_temp[8]={0,0,0,0,0,0,0,0};
    for(j=0;j<8;j++)    {
        while(num%primes[j]==0) {
            num=num/primes[j];
            primes_count_temp[j]++;
        }
    }
    for(j=0;j<8;j++)
        if(primes_count_temp[j]>primes_count[j])
            primes_count[j]=primes_count_temp[j];

        printf("\n %d",i);
        for(j=0;j<8;j++)
            printf("\t %d",primes_count_temp[j]);
    }
    printf("\nNET");
    for(j=0;j<8;j++)
        printf("\t%d",primes_count[j]);
    printf("\n");
    for(i=0;i<8;i++)
        while(primes_count[i])  {
            largest_num*=primes[i];
            primes_count[i]--;
        }

        printf("The answer is %d \n",largest_num);
        return 0;
    }
#包括
int main(){
int素数[8]={2,3,5,7,11,13,17,19};
int素数_count[8]={0,0,0,0,0,0};
int i,j,num,质点;
int最大_num=1;
printf(“\nNUM”);

对于(j=0;j非暴力方法

这是即时的!不需要一秒钟。运行代码来理解逻辑。它是用C编写的

#include <stdio.h>

int main()  {

int primes[8]={2,3,5,7,11,13,17,19};
int primes_count[8]={0,0,0,0,0,0,0,0};
int i,j,num,prime_point;
int largest_num=1;

printf("\nNUM");
for(j=0;j<8;j++)
    printf("\t%d",primes[j]);

for(i=2;i<=20;i++)  {
    num=i;
    int primes_count_temp[8]={0,0,0,0,0,0,0,0};
    for(j=0;j<8;j++)    {
        while(num%primes[j]==0) {
            num=num/primes[j];
            primes_count_temp[j]++;
        }
    }
    for(j=0;j<8;j++)
        if(primes_count_temp[j]>primes_count[j])
            primes_count[j]=primes_count_temp[j];

        printf("\n %d",i);
        for(j=0;j<8;j++)
            printf("\t %d",primes_count_temp[j]);
    }
    printf("\nNET");
    for(j=0;j<8;j++)
        printf("\t%d",primes_count[j]);
    printf("\n");
    for(i=0;i<8;i++)
        while(primes_count[i])  {
            largest_num*=primes[i];
            primes_count[i]--;
        }

        printf("The answer is %d \n",largest_num);
        return 0;
    }
#包括
int main(){
int素数[8]={2,3,5,7,11,13,17,19};
int素数_count[8]={0,0,0,0,0,0};
int i,j,num,质点;
int最大_num=1;
printf(“\nNUM”);

对于(j=0;j,这里有4种不同的方法获得结果(4种不同的方法获得GCD)+总时间。所有这些方法都基于以下观察:

其中:

LCM=最小公倍数
GCD=最大公约数

import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

public class A {

    final static int N = 20;

    static Map<Integer, String> messages = new HashMap<>();

    static {
        messages.put(0, "Euler - difference");
        messages.put(1, "modulo - recursive");
        messages.put(2, "modulo - iterative");
        messages.put(3, "BigInteger implementation");
    }

    private static long GCD0(long x, long y) {
        while (x != y) {
            if (x > y) {
                x -= y;
            } else {
                y -= x;
            }
        }
        return x;
    }

    private static long GCD1(long x, long y) {
        if (x % y == 0) {
            return y;
        }
        return GCD1(y, x % y);
    }

    private static long GCD2(long x, long y) {
        long aux;
        while (x % y != 0) {
            aux = y;
            y = x % y;
            x = aux;
        }
        return y;
    }

    private static long GCD3(long x, long y) {
        BigInteger xx = BigInteger.valueOf(x);
        BigInteger yy = BigInteger.valueOf(y);
        return xx.gcd(yy).longValue();
    }

    private static void doIt(int pos) throws Exception {

        System.out.print("\n" + messages.get(pos));
        printSpaces(25, messages.get(pos).length());

        Class cls = Class.forName("A");
        Object obj = cls.newInstance();
        Method method = cls.getDeclaredMethod("GCD" + pos, long.class,
                long.class);

        long start = System.nanoTime();

        long p = 1;
        for (int i = 2; i <= N; i++) {
            p = (p * i) / (long) method.invoke(obj, p, i);
        }
        long stop = System.nanoTime();
        System.out.println("\tTime: " + (stop - start) / 1000 + " microseconds");
        System.out.println(p);
    }

    private static void printSpaces(int total, int actualLength) {
        for (int i = 0; i < total - actualLength; i++) {
            System.out.print(" ");
        }
    }

    public static void main(String[] args) throws Exception {
        doIt(0);
        doIt(1);
        doIt(2);
        doIt(3);
    }
}
def getGCD(a,b):
   while(True):
      if(a%b != 0):
          temp = b
          b = a%b
          a = temp
      else:
          return b
          break

注意:我使用了反射来更容易地调用这些方法,但您可以直接调用该方法以获得更好的性能和可读性。

这里有4种不同的方法来获得结果(4种不同的获得GCD的方法)+总时间
。所有这些都基于以下观察结果:

其中:

LCM=最小公倍数
GCD=最大公约数

import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

public class A {

    final static int N = 20;

    static Map<Integer, String> messages = new HashMap<>();

    static {
        messages.put(0, "Euler - difference");
        messages.put(1, "modulo - recursive");
        messages.put(2, "modulo - iterative");
        messages.put(3, "BigInteger implementation");
    }

    private static long GCD0(long x, long y) {
        while (x != y) {
            if (x > y) {
                x -= y;
            } else {
                y -= x;
            }
        }
        return x;
    }

    private static long GCD1(long x, long y) {
        if (x % y == 0) {
            return y;
        }
        return GCD1(y, x % y);
    }

    private static long GCD2(long x, long y) {
        long aux;
        while (x % y != 0) {
            aux = y;
            y = x % y;
            x = aux;
        }
        return y;
    }

    private static long GCD3(long x, long y) {
        BigInteger xx = BigInteger.valueOf(x);
        BigInteger yy = BigInteger.valueOf(y);
        return xx.gcd(yy).longValue();
    }

    private static void doIt(int pos) throws Exception {

        System.out.print("\n" + messages.get(pos));
        printSpaces(25, messages.get(pos).length());

        Class cls = Class.forName("A");
        Object obj = cls.newInstance();
        Method method = cls.getDeclaredMethod("GCD" + pos, long.class,
                long.class);

        long start = System.nanoTime();

        long p = 1;
        for (int i = 2; i <= N; i++) {
            p = (p * i) / (long) method.invoke(obj, p, i);
        }
        long stop = System.nanoTime();
        System.out.println("\tTime: " + (stop - start) / 1000 + " microseconds");
        System.out.println(p);
    }

    private static void printSpaces(int total, int actualLength) {
        for (int i = 0; i < total - actualLength; i++) {
            System.out.print(" ");
        }
    }

    public static void main(String[] args) throws Exception {
        doIt(0);
        doIt(1);
        doIt(2);
        doIt(3);
    }
}
def getGCD(a,b):
   while(True):
      if(a%b != 0):
          temp = b
          b = a%b
          a = temp
      else:
          return b
          break
附言:我使用了反射来更容易地调用这些方法,但是你可以调用methodo