素数(线性筛法)

题目描述

本题已更新,从判断素数改为了查询第k小的素数

提示:如果你使用 cin 来读入,建议使用 std::ios::sync_with_stdio(0) 来加速。

如题,给定一个范围n,有 q个询问,每次输出第k小的素数。

输入格式

第一行包含两个正整数 n q,分别表示查询的范围和查询的个数。

接下来 q 行每行一个正整数k ,表示查询第 k 小的素数。

输出格式

输出 q 行,每行一个正整数表示答案。

样例

【样例输入】

复制代码
100 5
1
2
3
4
5

【样例输出】

复制代码
2
3
5
7
11

一些想法

主函数部分:优化输入输出。输入两个数,调用函数找从 2~n 中的质数。输出要求大小的质数。(记得换行)

自定义函数部分:(设定全局变量数组,bool 标记是不是质数,int 储存质数,还定义一个数计数有几个质数)初始化标记数组全部是 true(假装一开始全是质数),特殊标记 1 不是质数。

循环找质数,如果标记这个数是质数,先将计数器加一,然后将这个数放进数组。

然后循环,根据线性筛法将质数×当前数(质数或合数)标记为合数(非质数)。因为每一个合数都可以分解为:合数×质数或质数×质数。

优化部分:当前数能够整除一个质数,说明这个质数是当前数的最小质因子(第一个能整除的),所以后面的合数应该由更小的数标记,要退出(避免重复)。以次来达到让每个合数恰好被其最小质因子标记一次的目的。

AC代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
bool b[100000010];
int cnt=0;
int a[6000010];
void zs(int n){
	memset(b,true,sizeof(b));
	b[1]=false;
	for(int i=2;i<=n;i++){
		if(b[i]==true){
			a[++cnt]=i;
		}
		for(int j=1;j<=cnt&&(long long)i*a[j]<=n;j++){
			b[a[j]*i]=false;
			if(i%a[j]==0) break;
		}
	}
}
int main(){
	std::ios::sync_with_stdio(0);
	cin.tie(0);//优化处理
	int n,q;
	cin>>n>>q;
	zs(n);
	while(q--){
		int k;
		cin>>k;
		cout<<a[k]<<"\n";
	}
	return 0;
}

易错点

1.在核心循环时, 条件 i*a[j]<=n 没有强制转换类型,导致测试点过大爆掉。

因为,i*a[j]<=n 有可能会超出 int 范围(很大),所以要以防万一,强制转换为 long long 类型,这样就不会爆了。

2.没有写自定义函数,而是直接在主函数里写核心过程。只要测试点大一点,就会超时(TLE)。

因为:函数封装使代码结构更清晰,便于编译器优化(如内联、缓存利用),减少冗余计算;而无函数时代码逻辑混乱,易重复执行无效操作,且难以利用编译器优化,导致运行效率下降。

3.将 bool b[100000010] ;和 int a[6000010]; 设为局部变量,导致爆栈,但是开小一点又过不了大的测试点。

所以,要设为全局变量才行,因为全局变量在程序开始时从全局存储区分配静态内存空间,只要系统可用内存足够,一般能正常分配;而若作为局部变量在主函数等函数内部定义,其从栈中分配内存,栈空间有限,大数组容易导致栈溢出从而报错,所以在主函数等函数内部定义会爆,定义为全局变量在程序开始时一般不会爆。

4.用 vector 会超时。

这里用一维数组就不会超时。因为 vector 访问速度慢,而全局数组在程序启动时一次性分配,无运行时开销,而且 vector 在函数内定义大vector,频繁的内存分配/释放造成开销。vector的动态扩容机制(倍增策略)也会导致临时内存需求翻倍。但是一维数组连续内存布局,完美适配CPU缓存预取机制,还可以用 memset 快速初始化(比vector构造函数快得多)。

所以,对于固定规模的大规模数据处理,优先使用全局数组而非vector。

相关推荐
莹莹学编程—成长记2 小时前
TCP/IP五层模型+网络传输基本流程
网络·c++
ajole2 小时前
C++学习笔记——C++11
数据结构·c++·笔记·学习·算法·stl
轩情吖2 小时前
Qt容器类控件之QGroupBox与QTabWidget
开发语言·c++·qt·qgroupbox·qtabwidget·桌面级开发
helloworldandy2 小时前
C++安全编程指南
开发语言·c++·算法
OnYoung2 小时前
设计模式在C++中的实现
开发语言·c++·算法
zmzb01032 小时前
C++课后习题训练记录Day85
开发语言·c++·算法
2301_822366352 小时前
C++中的协程编程
开发语言·c++·算法
m0_736919102 小时前
C++中的事件驱动编程
开发语言·c++·算法
热爱编程的小刘2 小时前
Lesson03---类与对象(中篇)
c++