针对CSP-J/S的冲刺训练:Day 2 基础题

发布时间:2024年01月03日

一、审题

时间限制:1000ms ? ? ? ? ? ? ? ?内存限制:256MB ? ? ? ? ? ? ? ?AC率:94.28%

题目描述

筛1~n之间的质数。

输入描述

一行,一个正整数n(1 <= n <= 2147483647)。

输出描述

一行,几个用西文逗号+一个空格隔开的正整数,表示1~n之间的质数。

样例

输入

58

输出

2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,?

提示

1 <= n <= 2147483647

一、审题

1. 普通质数筛法

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    // 输入
    int n;
    cin >> n;

    // 筛质数
    for (int num = 1; num <= n; num++)
    {
        for (int i = 2; i <= sqrt(num); i++)
        {
            if (num % i == 0)
            {
                break; // 可以被整除,说明不是质数
            }
        }
        cout << num << ", ";
    }
    return 0;
}

【时间复杂度】O(n*sqrt(n))

【评价】这个算法并不好,不适用于所有的题目。这种算法的运行效率极低。

【评价依据】一共测试了86组平台题目,平均AC率只有可怜的16%不到。

?2. 阿拉托斯特尼筛法

#include <iostream>
using namespace std;

int main()
{
    int n;
    cin >> n;

    // 创建一个标记数组,默认都为质数
    bool isPrime[2147483650];
    for (int i = 1; i <= n; i++) 
    {
        isPrime[i] = true;
    }

    // 0和1不是质数,从2开始筛选
    isPrime[0] = isPrime[1] = false;

    // 遍历筛选标记
    for (int i = 2; i <= sqrt(n); i++)
    {
        if (isPrime[i])
        {
            // 将i的倍数标记为非质数
            for (int j = i * i; j <= n; j += i)
            {
                isPrime[j] = false;
            }
        }
    }

    // 输出质数
    for (int i = 2; i <= n; i++) 
    {
        if (isPrime[i]) {
            cout << i << ", ";
        }
    }
    return 0;
}

【时间复杂度】O(n*sqrt(n))

【评价】这个算法的确比上一个算法好了,但是由于时间复杂度接近,所以很难通过测试。

【评价依据】一共测试了93组平台题目(包括专门的阿拉托斯特尼筛法),平均AC率已经有37.28%左右了。但是,有几个报错,是因为有些编译器不支持isPrime[0] = isPrime[1] = false;这种写法。

还有什么方法?敬请期待C++知识点总结!

文章来源:https://blog.csdn.net/joe_g12345/article/details/135370794
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。