题目链接
题目描述
给定 个正整数,对于每个整数
,请你判断
是否为质数(素数)。若是,则输出
Yes
,否则输出 No
。
解题思路
本题要求对多个数字进行质数判断。如果对每个查询都独立使用试除法(检查从 到
的因子),当查询数量巨大时,总时间复杂度可能会很高,导致超时。
考虑到查询的数字范围是固定的,这是一个典型的可以使用预处理来优化的场景。对于质数判断,最经典高效的预处理算法是埃拉托斯特尼筛法(简称埃氏筛)。
-
核心思想:
埃氏筛的基本思想是,从最小的质数
开始,依次将其所有倍数标记为“合数”。然后找到下一个未被标记的数(它必然是质数,例如
),再将其所有倍数标记为合数。重复此过程,直到完成筛选。
-
算法步骤:
-
创建一个布尔数组
,大小为数据范围的上限
,并初始化所有值为
,代表假设所有数都是质数。
-
根据定义,
和
不是质数,所以设置
。
-
从
开始外层循环,循环条件为
。
-
在循环中,如果
仍然为
,说明
是一个质数。
-
对于这个质数
,我们启动一个内层循环,将其所有倍数(从
开始)都标记为合数,即设置
。
-
优化:内层循环从
开始,是因为任何小于
的
的倍数,例如
(
),必然有一个小于
的质因子,因此它已经被前面的步骤筛掉了。
-
-
处理查询:
-
在程序开始时,我们先执行一次埃氏筛法,预处理出
范围内所有数的质数属性。
-
对于接下来的每一个查询
,我们只需要直接查找
的值即可,可以在
的时间内得到答案。
-
代码
#include <iostream>
#include <vector>
using namespace std;
const int MAX_X = 1000001;
vector<bool> is_prime(MAX_X, true);
void sieve() {
is_prime[0] = is_prime[1] = false;
for (int p = 2; p * p < MAX_X; ++p) {
if (is_prime[p]) {
for (int i = p * p; i < MAX_X; i += p) {
is_prime[i] = false;
}
}
}
}
int main() {
sieve();
int n;
cin >> n;
while (n--) {
int x;
cin >> x;
if (is_prime[x]) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
}
return 0;
}
import java.util.Scanner;
import java.util.Arrays;
public class Main {
static final int MAX_X = 1000001;
static boolean[] is_prime = new boolean[MAX_X];
static {
Arrays.fill(is_prime, true);
is_prime[0] = is_prime[1] = false;
for (int p = 2; p * p < MAX_X; p++) {
if (is_prime[p]) {
for (int i = p * p; i < MAX_X; i += p) {
is_prime[i] = false;
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
while (n-- > 0) {
int x = sc.nextInt();
if (is_prime[x]) {
System.out.println("Yes");
} else {
System.out.println("No");
}
}
}
}
MAX_X = 1000001
is_prime = [True] * MAX_X
def sieve():
is_prime[0] = is_prime[1] = False
for p in range(2, int(MAX_X**0.5) + 1):
if is_prime[p]:
for i in range(p * p, MAX_X, p):
is_prime[i] = False
def main():
sieve()
n = int(input())
for _ in range(n):
x = int(input())
if is_prime[x]:
print("Yes")
else:
print("No")
if __name__ == "__main__":
main()
算法及复杂度
-
算法:数论、埃拉托斯特尼筛法
-
时间复杂度:预处理阶段使用埃氏筛法,时间复杂度为
,其中
是需要判断的数的最大值。预处理完成后,每次查询的复杂度为
。对于
次查询,总时间复杂度为
。
-
空间复杂度:需要一个布尔数组来存储每个数是否为质数,空间复杂度为
。