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