NC54580 素数分布

发布时间 2023-08-25 01:30:42作者: 空白菌

题目链接

题目

题目描述

素数分布函数 \(\pi (n)\) 表示小于或等于n的素数的数目。例如 \(\pi (10)=4\)(2,3,5,7是素数)。这个函数涉及到许多高等数论的内容,甚至和黎曼猜想挂钩,目前还有很多数学家正在不断探索其中的奥秘。千里之行始于足下,现在你开始关心一个问题:在正整数域中素数的分布是怎么样的。为了探索这个问题,你需要计算出一些 \(\pi (n)\) 的值。

输入描述

第一行一个整数 \(T(T \le 1000)\),表示数据的组数。
接下来一共T行,第 \(i+1(1 \le i \le T)\) 行表示第i组数据。每行一个正整数 \(n (n\le 1000)\)

输出描述

输出T行,第i行对应输入的第i组数据。每行一个正整数,表示 \(\pi (n)\) 的值。

示例1

输入

1
10

输出

4

题解

知识点:筛法,前缀和。

线性筛完素数后,对标记数组做前缀和即可。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int N = 1007;
int vis[N];
vector<int> prime;
void get_prime(int n) {
    for (int i = 2;i <= n;i++) {
        if (!vis[i]) prime.push_back(i);
        for (int j = 0;j < prime.size() && i * prime[j] <= n;j++) {
            vis[i * prime[j]] = 1;
            if (!(i % prime[j])) break;
        }
    }
}

bool solve() {
    int n;
    cin >> n;
    cout << n - vis[n] << '\n';
    return true;
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int t = 1;
    cin >> t;
    get_prime(1007);
    vis[1] = 1;
    for (int i = 1;i <= 1000;i++) vis[i] += vis[i - 1];
    while (t--) {
        if (!solve()) cout << -1 << '\n';
    }
    return 0;
}