import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
// 判断一个数是否为质数的暴力方法
public static boolean isPrime(int x) {
if (x < 2) return false; // 小于2的数不是质数
// 从2遍历到根号x,看有没有能整除的
for (int i = 2; i * i <= x; i++) {
if (x % i == 0) {
return false; // 能整除,不是质数
}
}
return true; // 遍历完没找到因数,是质数
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); // 查询次数
//对于有n次的查询都这样来计算
while (n-- > 0) {
int l = sc.nextInt();
int r = sc.nextInt();
int count = 0;
// 暴力遍历区间[l, r]的每一个数,逐个判断
for (int x = l; x <= r; x++) {
if (isPrime(x)) {
count++;
}
}
System.out.println(count);
}
sc.close();
}
}
2.埃氏筛 + 前缀和的优化解法
java复制代码
import java.util.Scanner;
public class Main {
// 题目最大范围:数字最大到 10^6
public static final int MAX = 1000000;
public static void main(String[] args) {
// ===================== 第一步:埃氏筛 筛出所有质数 =====================
// isPrime[i] = true 表示 i 是质数
boolean[] isPrime = new boolean[MAX + 1];
// 1. 先假设所有数都是质数
for (int i = 2; i <= MAX; i++) {
isPrime[i] = true;
}
// 2. 核心筛法:把质数的倍数全部标记为非质数
for (int i = 2; i * i <= MAX; i++) {
// 如果 i 是质数,就筛掉它所有倍数
if (isPrime[i]) {
// 从 i*i 开始筛,效率更高(前面的小倍数已被筛过)
for (int j = i * i; j <= MAX; j += i) {
isPrime[j] = false;
}
}
}
// ===================== 第二步:构建质数数量前缀和 =====================
// preSum[i] = 1~i 之间有多少个质数
int[] preSum = new int[MAX + 1];
for (int i = 1; i <= MAX; i++) {
// 前 i 个的数量 = 前 i-1 个的数量 + 当前是不是质数(是就+1)
preSum[i] = preSum[i - 1] + (isPrime[i] ? 1 : 0);
}
// ===================== 第三步:处理查询(O(1)) =====================
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); // 有多少次查询
while (n-- > 0) {
int l = sc.nextInt();
int r = sc.nextInt();
// 区间 [l, r] 的质数数量 = 1~r - 1~(l-1)
int ans = preSum[r] - preSum[l - 1];
System.out.println(ans);
}
}
}