素数回文以及素数相关总结
素数回文以及素数相关总结
- 普通筛素数法
- 埃式筛法
- 优化筛法
- 整数分解(唯一分解定理)
- 约数枚举
- Hdu - 1431. 素数回文
普通筛素数法
这个也是普通的素数判定的方法,这个方法判定素数时间复杂度为O (sqrt(n))。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
static ArrayList<Integer> sieve(boolean[] is_prime, int MAX) { ArrayList<Integer> prime = new ArrayList<>(); is_prime[0] = is_prime[1] = false; // 01 不是素数 boolean flag; for (int i = 2; i <= MAX; i++) { flag = true; for (int j = 2; j * j <= i; j++) {// 根号i的时间复杂度 if (i % j == 0) { is_prime[i] = false; flag = false; break; } } if (flag) { prime.add(i); is_prime[i] = true; } } return prime; } |
埃式筛法

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//经典的埃式筛法 static ArrayList<Integer> sieve(boolean[] is_prime, int MAX) { ArrayList<Integer> prime = new ArrayList<>(); Arrays.fill(is_prime, true); is_prime[0] = is_prime[0] = false; for (int i = 2; i <= MAX; i++) { if (is_prime[i]) { prime.add(i); for (int j = 2 * i; j <= MAX; j += i) is_prime[j] = false; } } return prime; } |
优化筛法
上面的方法还是有一些重复的计算,比如说在搞定素数
2的时候,筛选掉6 (2 + 2 + 2);而在搞定素数3的时候,也要筛选掉6 (3 + 3),所以此时重复筛选;解决办法是 只筛选小于等于
i的素数和i的乘积,这样可以尽量的的减少重复的筛选,也不会遗漏;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17//优化筛法 static ArrayList<Integer> sieve2(boolean[] is_prime, int MAX) { ArrayList<Integer> prime = new ArrayList<>(); Arrays.fill(is_prime, true); is_prime[0] = is_prime[0] = false; for (int i = 2; i <= MAX; i++) { if (is_prime[i]) prime.add(i); for (int j = 0; j < prime.size() && prime.get(j) <= MAX / i; j++) {// MAX/i防止溢出 is_prime[prime.get(j) * i] = false; //筛掉 (小于等于i的素数 * i) 构成的合数 if (i % prime.get(j) == 0) //如果 i是 < i的素数的倍数 就不用筛了 break; } } return prime; }
整数分解(唯一分解定理)
题目链接
https://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/1634.html
题目

解析

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
import java.io.BufferedInputStream; import java.util.*; public class Main { static ArrayList<Integer> sieve(int MAX) { ArrayList<Integer> prime = new ArrayList<>(); boolean[] is_prime = new boolean[MAX + 1]; Arrays.fill(is_prime, true); is_prime[0] = is_prime[1] = false; for (int i = 2; i <= MAX; i++) { if (is_prime[i]) { prime.add(i); for (int j = 2 * i; j <= MAX; j += i) { is_prime[j] = false; } } } return prime; } public static void main(String[] args) { Scanner cin = new Scanner(new BufferedInputStream(System.in)); int T = cin.nextInt(); while (T-- > 0) { int n = cin.nextInt(); ArrayList<Integer> prime = sieve(n); boolean isFirst = true; for (int i = 0; i < prime.size(); i++) { int num = prime.get(i); while (n % num == 0) { if (isFirst) { System.out.print(num); isFirst = false; } else System.out.print("*" + num); n /= num; } } System.out.println(); } } } |
约数枚举
就是得到某个数的约数,和普通筛法有点像:

这里把上面的整数分解的保存也贴在这个代码里面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
import java.util.ArrayList; import java.util.HashMap; public class TestPrime { //约数枚举 static ArrayList<Integer> divisor(int n){ ArrayList<Integer> res = new ArrayList<>(); for (int i = 1; i * i <= n; i++){ if(n % i == 0) res.add(i); if(i != n/i) res.add(n/i); } return res; } //整数分解 static HashMap<Integer,Integer> prime_factor(int n){ HashMap<Integer,Integer> map = new HashMap<>(); for(int i = 2; i * i <= n; i++){ while(n % i == 0){ if(map.containsKey(i)) { map.put(i, map.get(i) + 1); }else { map.put(i,1); } n /= i; } } if(n != 1) map.put(n,1); return map; } public static void main(String[] args){ System.out.println(divisor(12)); System.out.println("----测试分解素因子(唯一分解定理)-----"); HashMap<Integer,Integer>map = prime_factor(12); for(Integer num : map.keySet()){ System.out.println(num + " " + map.get(num)); } } } |
运行结果:

Hdu - 1431. 素数回文
题目链接
题目

解析
先用素数筛法筛出
0~9989899之间的素数,然后再遍历一遍,判断一下是不是回文,最后判断是不是在那个区间即可;注意这里使用的三种筛法,第一种会超时,第二种和第三种可以通过;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123import java.io.BufferedInputStream; import java.util.*; /** * 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1431 */ public class Main { //提交时改成main // 经典筛法,超时 static ArrayList<Integer> primary(boolean[] is_prime,int MAX){ ArrayList<Integer> prime = new ArrayList<>(); is_prime[0] = is_prime[1] = false; // 01 不是素数 boolean flag; for(int i = 2; i <= MAX; i++){ //范围是1000 我筛选 0~2000内的素数 flag = true; for(int j = 2; j * j <= i; j++){// 根号i的时间复杂度 if(i % j == 0){ is_prime[i] = false; flag = false; break; } } if(flag){ prime.add(i); is_prime[i] = true; } } return prime; } //经典的埃式筛法 static ArrayList<Integer> sieve(boolean[] is_prime,int MAX){ ArrayList<Integer> prime = new ArrayList<>(); Arrays.fill(is_prime,true); is_prime[0] = is_prime[0] = false; for(int i = 2; i <= MAX; i++){ if(is_prime[i]){ prime.add(i); for(int j = 2 * i; j <= MAX; j+=i) is_prime[j] = false; } } return prime; } //优化筛法 static ArrayList<Integer> sieve2(boolean[] is_prime,int MAX){ ArrayList<Integer> prime = new ArrayList<>(); Arrays.fill(is_prime,true); is_prime[0] = is_prime[0] = false; for(int i = 2; i <= MAX; i++){ if(is_prime[i]) prime.add(i); for(int j = 0; j < prime.size() && prime.get(j) <= MAX / i; j++) { is_prime[prime.get(j) * i] = false; //筛掉 (小于等于i的素数 * i) 构成的合数 if(i % prime.get(j) == 0) //如果 i是 < i的素数的倍数 就不用筛了 break; } } return prime; } static boolean isPalindrome(int num){ int oldNum = num; int newNum = 0; //反过来计算 while(num > 0){ newNum = newNum * 10 + num % 10; num /= 10; } return newNum == oldNum; } static final int maxn = 9989899; //题目中最大的回文素数 public static void main(String[] args) { Scanner cin = new Scanner(new BufferedInputStream(System.in)); boolean[] is_prime = new boolean[maxn + 1]; // primary(is_prime,maxn); //超时 // sieve(is_prime,maxn); // ok sieve2(is_prime,maxn); // ok fast ArrayList<Integer> res = new ArrayList<>(); for(int i = 0; i <= maxn; i++ ){ if(is_prime[i] && isPalindrome(i)) res.add(i); } while(cin.hasNext()){ int a = cin.nextInt(); int b = cin.nextInt(); int num = 0; for(int i = 0; i < res.size(); i++){ num = res.get(i); if(num < a) continue; else if(num > b) break; // 直接退出 else System.out.println(num); } System.out.println(); } } }
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 xhj的博客!