1.质数
在大于1的整数中,如果只包含1和它本身这两个约数,就称为质数或者素数。
(1)试除法判定质数
时间复杂度为O(sqrt(n))
import java.util.Scanner;
public class Main{
public static void is_prime(int a){
if(a < 2){
System.out.println("No");//注意这里测试数据是从1开始的,所以要加上一个判断
return;
}
for(int i = 2; i <= a / i; i ++){//i<= a/i这种写法比较好,其它的可能会溢出或者效率低什么的
if(a % i == 0){
System.out.println("No");
return;
}
}
System.out.println("Yes");
return;
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
while(n -- > 0){
int a = sc.nextInt();
is_prime(a);
}
}
}
(2)分解质因数(试除法)
1. 时间复杂度为O(sqrt(n))
2. n中最多只包含一个大于sqrt(n)的质因子
import java.util.*;
public class Main{
public static void divide(int n){
for(int i = 2; i <= n / i; i ++){
if(n % i == 0){
int s = 0;
while(n % i == 0){
n /= i;
s ++;
}
System.out.println(i + " " + s);
}
}
//一个数n最多只有一个大于sqrt(n)的质因子
//如果n>1,说明n就是那个质因子
if(n > 1) System.out.println(n + " 1");
System.out.println();
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
while(n -- > 0){
int a = sc.nextInt();
divide(a);
}
}
}
(3)筛质数(朴素,埃氏,线性)
朴素法O(nlogn)
埃氏筛 O(nloglogn)
线性筛(欧拉筛)O(n)
import java.util.*;
public class Main{
static int N = 1000010, cnt, n;
static int[] pr = new int[N];
static boolean[] st = new boolean[N];
//朴素法
public static void find(int x){
for(int i = 2; i <= n; i ++){
if(!st[i]) pr[cnt ++] = i;
for(int j = i + i; j <= n; j += i){
st[j] = true;
}
}
}
//埃氏法
public static void find1(int x){
for(int i = 2; i <= x; i ++){
if(!st[i]){
pr[cnt ++] = i;
for(int j = i + i; j <= n; j += i){
st[j] = true;
}
}
}
}
//欧拉法(线性)
//每个n只会被它的最小质因子筛掉
//每个数只有一个最小质因子,所以每个数只会被筛一次,不会重复筛
public static void find2(int x){
for(int i = 2; i <= x; i ++){
if(!st[i]) pr[cnt ++] = i;
for(int j = 0; pr[j] <= n / i; j ++){
st[pr[j] * i] = true;
if(i % pr[j] == 0) break;//pr[j]一定是i的最小质因子
}
}
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
find2(n);
System.out.print(cnt);
}
}
2.约数
(1)试除法求一个数的所有约数
1. Java的集合排序:Collections.sort、list.sort和list.stream().sorted方法详解-CSDN博客
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
while(n -- > 0){
int a = sc.nextInt();
find(a);
}
}
public static void find(int a){
ArrayList<Integer> list = new ArrayList<>();
for(int i = 1; i <= a / i; i ++){//遍历一对约数中较小的那个
if(a % i == 0){
list.add(i);//把较小的那个约数放进容器
if(i != a / i) list.add(a / i);//特判,如果这一对彼此不相等,那么都放进去
}
}
//时间复杂度为O(nlogn)
Collections.sort(list);//题目说要从小到大,所以要排下序
for(int i:list){
System.out.print(i + " ");
}
System.out.println();
}
}
(2)约数的个数
1. 求约数个数(公式、原理以及Java代码实现)_java约数-CSDN博客
2,Java HashMap getOrDefault() 方法 | 菜鸟教程 (runoob.com)
公式 (a1+1)*(a2+1)*(a3+1)*...*(ak+1)
import java.util.*;
public class Main{
static int mod = (int)1e9 + 7;
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Map<Integer, Integer> map = new HashMap<>();//构造一个哈希表
//以下是用了分解质因数的模板
while(n -- > 0){
int x = sc.nextInt();
for(int i = 2; i <= x / i; i ++){
while(x % i == 0){
x /= i;
map.put(i, map.getOrDefault(i, 0) + 1);
}
}
if(x > 1) map.put(x, map.getOrDefault(x, 0) + 1);
}
long res = 1;
for(int key: map.values()){
res = res * (key + 1) % mod;//这里不可以写成 res *= (key + 1) % mod
}
System.out.print(res);
}
}
(3)约数之和
1、 约数之和 - Y2ZH - 博客园 (cnblogs.com)
2、Java的Map中的map.keySet()方法-CSDN博客
import java.util.*;
public class Main{
static int mod = (int)1e9 + 7;
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Map<Integer, Integer> map = new HashMap<>();
while(n -- > 0){
int x = sc.nextInt();
for(int i = 2; i <= x / i; i ++){
while(x % i == 0){
x /= i;
map.put(i, map.getOrDefault(i, 0) + 1);
}
}
if(x > 1) map.put(x, map.getOrDefault(x, 0) + 1);
}
long res = 1;
for(int a : map.keySet()){
int b = map.get(a);
long t = 1;
while(b -- > 0){
t = (t * a + 1) % mod;//这里加1是因为b-->0没有算到0次方,所以要加上1
}
// p = a ^ 3 * b ^ 1;
// sum = (a ^ 0 + a ^ 1 + a ^ 2 + a ^ 3) * (b ^ 0 + b ^ 1)
res = res * t % mod;
}
System.out.print(res);
}
}
(4)求最大公约数(欧几里得算法-辗转相除法)
import java.util.*;
public class Main{
public static int gcd(int a, int b){
return b > 0? gcd(b, a % b) : a;//辗转相除法
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
while(n -- > 0){
int a = sc.nextInt();
int b = sc.nextInt();
System.out.println(gcd(a, b));
}
}
}