项目Euler#5(可被1到20的所有数字整除的最小正数):优化方法~JAVA
问题5:2520是最小的数字,可以被1到10的每个数字除,没有余数。 能被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))
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