质数、约数相关的算法实现

  • 基本概念
  • 质数
  • 判断一个数是不是质数:
  •  暴力遍历:
  •  优化:
  •  代码再次优化:
  • 埃式筛法
  • 求范围内的质数:
  • 代码
  • 埃式筛法
  • 合数
  • 质因数
  • 分解质因数
  • 约数
  • 判断约数数量
  • 分解质因数方法
  • 暴力
  • 最小公倍数
  • 最大公约数
  • api
  • 暴力获取
  • 辗转相除法(欧几里德算法)
  • 实现
  • 递归实现
  • 更相减损
  • 实现
  • 递归
  • 互质
  • 习题
  • 质数


基本概念


 因子/约数:因数是指整数a除以整数b(b≠0) 的商正好是整数而没有余数,我们就说b是a的因数。

 公约数:如果一个整数同时是几个整数的约数/因子,称这个整数为它们的公因数;

 最大公约数:公约数中最大的称为最大公约数

 质数:质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

 自然数:非负整数。


质数

判断一个数是不是质数:

public static boolean isPrime1(int prime) {
    //for (int i = 2; i <= prime; i++) 全部遍历
    /*
      由于质数可以变成2个因子的乘,那么如果一个因子大于sqrt(x)
       则另外一个小于sqrt(x),或者2个都是sqrt(x)
    */
   for (int i = 2; i <= Math.sqrt(prime); i++)
        if (prime % i == 0)
            return false;
   return true;
}
一个数不能被2整除,那么这个数一定不能被其他偶数整除,
public static boolean isPrime2(int prime) {
        if (prime <= 3)
            return prime > 1;
        if (prime % 2 == 0)
            return false;
        for (int i = 3; i <= Math.sqrt(prime); i += 2)
            if (prime % i == 0)
                return false;
        return true;
    }
(大于等于5的)质数一定和6的倍数相邻,一个是6x-1或6x+1
又因为6x-2/4一定能被2整除(2(x-1))
6x-3一定能被3整除
所以在1-6里面2,3,4,6都是不行的只有1和5可以
public static boolean isPrime(int prime) {
        if (prime <= 3)
            return prime > 1;
        if (prime % 6 != 1 && prime % 6 != 5)
            return false;
        for (int i = 5;  i <= Math.sqrt(prime); i += 6) // 乘法比除法快所以用i*i
            if (prime % i == 0 || prime % (i + 2) == 0)
                return false;
        return true;
    }

埃式筛法

判断一个数是不是不建议用这个方法

下文有具体介绍

求范围内的质数:

emm,可以知道的只有偶数(除了2)不是。所以外循环可以优化为

代码

/**
 * 返回范围内的质数数量
 * @param start
 * @param end
 * @return
 */
public static long countPrime(int start, int end){
    int i =start,count = 0;
    for (; i < end; i++)
        if (isPrime(i))
            count++;
    return count;
}

/**
 * 返回0-指定数的质数数量
 * @param end
 * @return
 */
public static long countPrime(int end){
    if (end < 4)
        return end - 1;
    return 2+countPrime(5,end);
}

埃式筛法



埃拉托色尼筛法(Sieve of Eratosthenes)是一种用于查找素数的简单而古老的算法。算法步骤如下:

  1. 创建一个长度为 java质因数分解 java求一个数的质因数_算法 + java质因数分解 java求一个数的质因数_整除_02 的布尔类型数组 java质因数分解 java求一个数的质因数_java_03,并将所有元素初始化为 java质因数分解 java求一个数的质因数_数据结构_04
  2. 设置 java质因数分解 java求一个数的质因数_java质因数分解_05 [ java质因数分解 java求一个数的质因数_java_06 ]和 java质因数分解 java求一个数的质因数_java质因数分解_05 [ java质因数分解 java求一个数的质因数_整除_02 ]为 java质因数分解 java求一个数的质因数_整除_09 ,因为 java质因数分解 java求一个数的质因数_java_06java质因数分解 java求一个数的质因数_整除_02
  3. java质因数分解 java求一个数的质因数_整除_12 开始循环到 java质因数分解 java求一个数的质因数_数据结构_13 { java质因数分解 java求一个数的质因数_算法 },如果 java质因数分解 java求一个数的质因数_java质因数分解_05 [ java质因数分解 java求一个数的质因数_数据结构_16 ]为 java质因数分解 java求一个数的质因数_数据结构_04 ,则将 java质因数分解 java求一个数的质因数_数据结构_16 的所有倍数(除了 java质因数分解 java求一个数的质因数_数据结构_16 本身)标记为 java质因数分解 java求一个数的质因数_整除_09 ,即设置 java质因数分解 java求一个数的质因数_java质因数分解_05 [ java质因数分解 java求一个数的质因数_java_22 ]= java质因数分解 java求一个数的质因数_整除_09 ( java质因数分解 java求一个数的质因数_java_22 = java质因数分解 java求一个数的质因数_数据结构_16 , java质因数分解 java求一个数的质因数_数据结构_16 ( java质因数分解 java求一个数的质因数_数据结构_16 + java质因数分解 java求一个数的质因数_整除_02 ), java质因数分解 java求一个数的质因数_数据结构_16 *( java质因数分解 java求一个数的质因数_数据结构_16 + java质因数分解 java求一个数的质因数_整除_12 )… 直到 java质因数分解 java求一个数的质因数_java_22 > java质因数分解 java求一个数的质因数_算法
  4. 遍历 java质因数分解 java求一个数的质因数_java质因数分解_05 []数组,将值为 java质因数分解 java求一个数的质因数_数据结构_04 的下标存储到另一个数组 java质因数分解 java求一个数的质因数_java_36 []中,这样就得到了从 java质因数分解 java求一个数的质因数_整除_12java质因数分解 java求一个数的质因数_算法

时间复杂度为java质因数分解 java求一个数的质因数_java质因数分解_39,空间复杂度为java质因数分解 java求一个数的质因数_数据结构_40

public ArrayList<Integer> getPrimes(int n){
        ArrayList<Integer> primes = new ArrayList<>();
        boolean[] f = new boolean[n+1];
        for (int i = 2; i < n + 1; i++) {
            if (!f[i]){
                primes.add(i);
                for (int j = i+i; j < n + 1; j+=i) {
                    f[j] = true;
                }
            }
        }
        return primes;
    }

合数

非质数就是合数

质因数

质因数(素因数或质因子)在数论里是指能整除给定正整数的质数。
除了1以外,两个没有其他共同质因子的正整数称为互质。

正整数的因数分解可将正整数表示为一连串的质因子相乘,质因子如重复可以用指数表示。

根据算术基本定理,任何正整数皆有独一无二的质因子分解式  。

质数只有一个质因子就是本身。

分解质因数

public ArrayList<Integer> zhiyin(int n){
        ArrayList<Integer> a = new ArrayList<>();
        for (int i = 2; i <= n; i++) {
            while (n % i == 0) {
                a.add(i);
                n /= i;
            }
        }
        return a;
    }

约数

约数,又称因数。整数a除以整数b(b≠0)除得的商正好是整数而没有余数,我们就说a能被b整除,或b能整除a。a称为b的倍数,b称为a的约数。

判断约数数量

约数个数定理是指:一个正整数N可以分解为质因数乘积 java质因数分解 java求一个数的质因数_算法_41,其中java质因数分解 java求一个数的质因数_数据结构_42为不同的质数,java质因数分解 java求一个数的质因数_java质因数分解_43为正整数,则N的约数个数为java质因数分解 java求一个数的质因数_数据结构_44个。

数学公式为:
java质因数分解 java求一个数的质因数_算法_45

其中,java质因数分解 java求一个数的质因数_算法_46表示N的约数个数。

分解质因数方法

public static long countDivisor(long divisor){
    long count = 1;
    for (long i = 2; i*i <= divisor; i++) {
        long numi = 0;
        while (divisor % i == 0){
            numi++;
            divisor/=i;
        }
        count*=numi+1;
    }if (divisor > 1)
         count*=2;
    return count;
}

暴力

public static int countDivisor1(int divisor) {
    int count = 0;
    int i = 1;
    /*for (int i = 1; i <= divisor; i++)
        if (divisor % i == 0)
            count++;*/
    for (; i*i < divisor; i++)
        if (divisor % i == 0)
            count+=2;
    return i*i==divisor?count+1:count;}

最小公倍数

如求 java质因数分解 java求一个数的质因数_算法_47java质因数分解 java求一个数的质因数_数据结构_48 的最小公倍数。
则最小公倍数等于 java质因数分解 java求一个数的质因数_java_49

2个数的乘积除以这2个数的最大公约数
public BigInteger aaa(int a,int b){
        BigInteger bi = BigInteger.valueOf(a);
        BigInteger bb = BigInteger.valueOf(b);
        return bi.multiply(bb)
                .divide(bi.gcd(bb));
    }

最大公约数

api

java可以直接使用api进行求解

public BigInteger aaa(int a,int b){
        return BigInteger.valueOf(a).gcd(BigInteger.valueOf(b));
    }

暴力获取

int big = Math.max(a, b);
int small = Math.min(a, b);
if (big % small == 0)
    return small;
for (int i = small / 2; i > 1; i--) {
    if (big % i == 0 && small % i == 0) 
        return i;    
}
return 1;

辗转相除法(欧几里德算法)

实现

int result = 0;
while (n != 0) {
    result = m % n;
    m = n;
    n = result;
}
return m;

递归实现

public static int gcd (int a,int b) {
    if(b==0)
        return a;
    else
        return gcd(b,a%b);
}

更相减损

实现

while(m != n) {
    if(m > n)
        m -= n;
    else
        n-= m;
}
return m;

递归

public static int gcd (int a,int b) {
    if (a==b) 
        return a;
    else if (a>b)
      a = a-b;    
    else
       b = b-a;
    return gcd(a, b);
}

互质

2个数互质,说明其最大公约数为1

static int gcd(int a, int b) {
        if (a % b == 0)
            return b;
        return gcd(b, a % b);
    }

习题

质数

蓝桥杯–超级质数蓝桥杯–最大和

待补充