#include <stdio.h> #include <stdlib.h> #define MAX_N 1000000 // 声明一个质数计数数组 int prime_count[MAX_N + 1]; // 埃拉托斯特尼筛法 void sieve_of_eratosthenes() { // 初始化质数数组,默认所有数都认为是质数 int is_prime[MAX_N + 1]; for (int i = 0; i <= MAX_N; i++) { is_prime[i] = 1; // 假设所有数都是质数 } is_prime[0] = is_prime[1] = 0; // 0和1不是质数 // 埃拉托斯特尼筛法 for (int i = 2; i * i <= MAX_N; i++) { if (is_prime[i]) { for (int j = i * i; j <= MAX_N; j += i) { is_prime[j] = 0; } } } // 计算每个数小于等于它的质数个数 prime_count[0] = 0; for (int i = 1; i <= MAX_N; i++) { prime_count[i] = prime_count[i - 1] + is_prime[i]; } } int main() { int T; scanf("%d", &T); // 读取查询次数 // 预处理所有质数信息 sieve_of_eratosthenes(); // 对于每个查询,输出小于等于n的质数个数 while (T--) { int n; scanf("%d", &n); printf("%d\n", prime_count[n]); } return 0; }
代码解析:
-
sieve_of_eratosthenes():
- 该函数使用埃拉托斯特尼筛法来标记质数。我们维护一个is_prime数组来标记每个数是否为质数。
- 对于每个质数 p,标记 p^2, p^2 + p, p^2 + 2p,… 为非质数。
- 然后,使用prime_count数组来记录每个数小于等于它的质数个数。
-
main():
- 首先读取查询次数T。
- 然后对每个查询n,直接输出prime_count[n],这表示小于等于n的质数个数。
时间复杂度:
- 埃拉托斯特尼筛法:时间复杂度为 O(nloglogn),其中 n= 10^6。
- 查询阶段:每次查询的时间复杂度是 O(1),因为我们直接查找预处理结果。
空间复杂度:
- 需要 O(n)的空间来存储is_prime和prime_count数组,最多需要 10^6 个元素。