质数、约数相关的算法实现
- 基本概念
- 质数
- 判断一个数是不是质数:
- 暴力遍历:
- 优化:
- 代码再次优化:
- 埃式筛法
- 求范围内的质数:
- 代码
- 埃式筛法
- 合数
- 质因数
- 分解质因数
- 约数
- 判断约数数量
- 分解质因数方法
- 暴力
- 最小公倍数
- 最大公约数
- 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)是一种用于查找素数的简单而古老的算法。算法步骤如下:
- 创建一个长度为 + 的布尔类型数组 ,并将所有元素初始化为
- 设置 [ ]和 [ ]为 ,因为 和
- 从 开始循环到 { },如果 [ ]为 ,则将 的所有倍数(除了 本身)标记为 ,即设置 [ ]= ( = , ( + ), *( + )… 直到 >
- 遍历 []数组,将值为 的下标存储到另一个数组 []中,这样就得到了从 到
时间复杂度为,空间复杂度为。
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可以分解为质因数乘积 ,其中为不同的质数,为正整数,则N的约数个数为个。
数学公式为:
其中,表示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;}
最小公倍数
如求 和 的最小公倍数。
则最小公倍数等于
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);
}
习题
质数
蓝桥杯–超级质数蓝桥杯–最大和
待补充