1 问题描述

Compute the Greatest Common Divisor of Two Integers using Sieve of Eratosthenes.

翻译:使用埃拉托色尼筛选法计算两个整数的最大公约数。(PS:最大公约数也称最大公因数,指两个或多个整数共有约数中最大的一个)

2 解决方案

2.1 埃拉托色尼筛选法原理简介

引用自百度百科:

埃拉托色尼筛选法(the Sieve of Eratosthenes)简称埃氏筛法,是古希腊数学家埃拉托色尼(Eratosthenes 274B.C.~194B.C.)提出的一种筛选法。 是针对自然数列中的自然数而实施的,用于求一定范围内的质数,它的容斥原理之完备性条件是p=H~。

具体求取质数的思想:

(1)先把1删除(现今数学界1既不是质数也不是合数)

(2)读取队列中当前最小的数2,然后把2的倍数删去

(3)读取队列中当前最小的数3,然后把3的倍数删去

(4)读取队列中当前最小的数5,然后把5的倍数删去

(5)如上所述直到需求的范围内所有的数均删除或读取

下面看一下执行上述步骤求不大于100的所有质数的一个示意图:

2.2 具体编码

本文求取两个数的最大公约数,采用质因数分解法:把每个数分别分解质因数,再把各数中的全部公有质因数提取出来连乘,所得的积就是这几个数的最大公约数。

例如:求24和60的最大公约数,先分解质因数,得24=2×2×2×3,60=2×2×3×5,24与60的全部公有的质因数是2、2、3,它们的积是2×2×3=12,所以,(24,60)=12。

此处,第一步,先使用埃拉托色尼筛选法求取不大于数A的所有质数,然后从这些质数中选取A的所有质因数;第二步,依照第一步思想求取数B的所有质因数;第三步,求取数A和数B公共质因数;第四步,输出数A和数B的最大公约数。

具体代码如下:

package com.liuzhen.ex1;

import java.util.Scanner;

public class SieveOfEratosthenes {
//返回一维数组,数组中的元素为不大于n的所有质数
public static int[] getPrime(int n){
int[] result1 = new int[n]; //定义一个一维数组,并从第2个元素依次初始化为相应的自然数
for(int i = 2;i < n+1;i++){
result1[i-1] = i;
}
for(int i = 2;i < n;i++){
for(int j = i+1;j < n+1;j++){
if(j % i == 0) //如果j能够整除i,使result[j-1]等于0
result1[j-1] = 0;
}
}
int[] result2 = getNoneZero(result1); //除去result数组中所有0元素
return result2; //数组中非零元素即为不大于n的所有质数
} //返回一维数组,该数组的元素为参数数组中所有不为0的元素值
public static int[] getNoneZero(int[] A){
int len = 0;
for(int i = 0;i < A.length;i++){
if(A[i] != 0)
len = len+1;
}
int[] result = new int[len];
int k = 0;
for(int i = 0;i < A.length;i++){
if(A[i] != 0){
result[k] = A[i];
k++;
}
}
return result;
} //求取一个数n的所有质因数(eg:24=2×2×2×3,则result[] = {2,2,2,3})
public static int[] getNprime(int n){
int[] primes = getPrime(n);
int[] result; //最终返回结果集
int len = 0; //返回结果集数组长度,初始化为0
for(int i = 0;i < primes.length;i++){
int temp = n;
while(temp % primes[i] == 0){
temp = temp/primes[i];
len++;
}
}
result = new int[len];
int k = 0;
for(int i = 0;i < primes.length;i++){
int temp = n;
while(temp % primes[i] == 0){
temp = temp/primes[i];
result[k] = primes[i];
k++;
}
}
return result;
} //返回两个一维数组中所有共同元素
public static int[] getCommonPrime(int[] A , int[] B){
int[] result;
int lenA = A.length;
int lenB = B.length;
if(lenA < lenB){
result = new int[lenA];
for(int i = 0;i < lenA;i++){
int temp = A[i];
for(int j = 0;j < lenB;j++){
if(temp == B[j]){
result[i] = A[i];
B[j] = 0;
break;
}
}
}
}
else{
result = new int[lenB];
for(int i = 0;i < lenB;i++){
int temp = B[i];
for(int j = 0;j < lenA;j++){
if(temp == A[j]){
result[i] = B[i];
A[j] = 0;
break;
}
}
}
}
int[] result1 = getNoneZero(result);
return result1;
} //求取数A和B的最大公约数
public static void getMaxCommonDivisor(int A,int B){
int[] primesA = getNprime(A); //数A所有质因子
int[] primesB = getNprime(B); //数B所有质因子
int[] resultPrime = getCommonPrime(primesA,primesB); //数A和数B的公共质因数
int maxCommonDivisor = 1;
System.out.println(A+"和"+B+"的公共质因数为:");
for(int i = 0;i < resultPrime.length;i++){
maxCommonDivisor *= resultPrime[i];
System.out.print(resultPrime[i]+"\t");
}
System.out.println();
System.out.print(A+"和"+B+"的最大公约数为:"+maxCommonDivisor);
} public static void main(String[] args){
System.out.println("请输入数字A和数字B的值:");
Scanner in = new Scanner(System.in);
int a = in.nextInt();
int b = in.nextInt();
getMaxCommonDivisor(a,b);
}
}

运行结果:

请输入数字A和数字B的值:
60
100和60的公共质因数为:
2 5
100和60的最大公约数为:20 请输入数字A和数字B的值:
48
60和48的公共质因数为:
2 3
60和48的最大公约数为:12 请输入数字A和数字B的值:
54
120和54的公共质因数为:
3
120和54的最大公约数为:6

Java实现埃拉托色尼筛选法的更多相关文章

  1. 算法笔记_012:埃拉托色尼筛选法(Java)

    1 问题描述 Compute the Greatest Common Divisor of Two Integers using Sieve of Eratosthenes. 翻译:使用埃拉托色尼筛选 ...

  2. 使用埃拉托色尼筛选法(the Sieve of Eratosthenes)在一定范围内求素数及反素数(Emirp)

    Programming 1.3 In this problem, you'll be asked to find all the prime numbers from 1 to 1000. Prime ...

  3. LeetCode Count Primes 求素数个数(埃拉托色尼筛选法)

    题意:给一个数n,返回小于n的素数个数. 思路:设数字 k =from 2 to sqrt(n),那么对于每个k,从k2开始,在[2,n)范围内只要是k的倍数的都删掉(也就是说[k,k2)是不用理的, ...

  4. java筛选法求素数

    这本身没什么,代码一堆 发来纪念下而已 本来刚学习java,编写输出100以内的素数 对于我这个有代码运行性能洁癖的人(但是本身又不懂算法)来说,不能忍 于是看了些资料 参考: http://blog ...

  5. 素数筛选法(prime seive)

    素数筛选法比较有名的,较常用的是Sieve of Eratosthenes,为古希腊数学家埃拉托色尼(Eratosthenes 274B.C.-194B.C.)提出的一种筛选法.详细步骤及图示讲解,还 ...

  6. Eratosthenes筛选法构造1-n 素数表

    筛选法:对于不超过n的每个非负整数p,删除2p,3p,4p...当处理完所有数之后,还没没删除的就是素数. 代码中进行了相应的优化. 本代码功能,输入一个数,输出从1-该数之间的素数.功能待完善,可将 ...

  7. ACM/ICPC 之 数论-素数筛选法 与 "打表"思路(POJ 1595)

    何为"打表"呢,说得简单点就是: 有时候与其重复运行同样的算法得出答案,还不如直接用算法把这组数据所有可能的答案都枚举出来存到一个足够大的容器中去-例如数组(打表),然后再输入数据 ...

  8. HDU1215(筛选法)

    题意:求n的所有因子和: 思路:类似于筛选法求素数的思想,只有第一次的时候了解过它的思想,然后就只是用来求素数,思想的运用反而少: 筛选法求素数: int prime() { memset(vis, ...

  9. POJ 3978 Primes(素数筛选法)

    题目 简单的计算A,B之间有多少个素数 只是测试数据有是负的 //AC //A和B之间有多少个素数 //数据可能有负的!!! #include<string.h> #include< ...

随机推荐

  1. C#枚举高级战术

    文章开头先给大家出一道面试题: 在设计某小型项目的数据库(假设用的是 MySQL)时,如果给用户表(User)添加一个字段(Roles)用来存储用户的角色,你会给这个字段设置什么类型?提示:要考虑到角 ...

  2. leeCode刷题 1078

    给出第一个词 first 和第二个词 second,考虑在某些文本 text 中可能以 "first second third" 形式出现的情况,其中 second 紧随 firs ...

  3. 帝国cms 批量替换 字段内容包含的 指定的 关键字 SQL命令

    帝国cms 批量替换 字段内容包含的 指定的 关键字update phome_ecms_news_data_1 set newstext=replace(newstext,'原来','现在');

  4. mac下charles使用

    设置charles  电脑上一次性的工作 1 下载下面两个文件(这里版本自己定) a charles-proxy-4.1.4.dmg b charles4.1.4的副本.jar 2 进行charles ...

  5. zip压缩文件(二)

    普通压缩文件以20M大小的文件为例 public static void main(String[] args) { String source = "F:\\demo\\择天记 第5季 第 ...

  6. 手机APP自动化环境搭建

    1 摘要 近年来,随着移动应用从数量上和逻辑复杂程度上的增长,以及产品发布周期的紧缩,使得回归测试迫在眉睫,鉴于此APP自动化测试变得越来流行,当前主流的APP自动化工具有:Appium.Roboti ...

  7. Sentinel源码解析二(Slot总览)

    写在前面 本文继续来分析Sentinel的源码,上篇文章对Sentinel的调用过程做了深入分析,主要涉及到了两个概念:插槽链和Node节点.那么接下来我们就根据插槽链的调用关系来依次分析每个插槽(s ...

  8. express.static设置缓存

    之前因为服务器端脚本不大,都是直接手写,按请求文件后缀名设置cache-control的max-age. 今天决定还是改成express,发现原来express.static()方法设置缓存,直接在参 ...

  9. Lvs 调度算法

    lvs scheduler:仅根据IP和端口进行调度 静态方法:仅根据算法本身进行调度,不考虑当前服务器实际负载情况:保证起点公平 RR:round robin, 轮调,轮询,轮叫: 调度器通过&qu ...

  10. poj2455 k条路最小化最长边

    Secret Milking Machine Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12414   Accepted ...