一、审题
时间限制: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++知识点总结!