素数(线性筛法)

题目描述

本题已更新,从判断素数改为了查询第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。

相关推荐
H Journey1 小时前
C++之 CMake、CMakeLists.txt、Makefile
开发语言·c++·makefile·cmake
研究点啥好呢5 小时前
Github热门项目推荐 | 创建你的像素风格!
c++·python·node.js·github·开源软件
_dindong5 小时前
cf1091div2 C.Grid Covering(数论)
c++·算法
沫璃染墨5 小时前
C++ string 从入门到精通:构造、迭代器、容量接口全解析
c语言·开发语言·c++
6Hzlia6 小时前
【Hot 100 刷题计划】 LeetCode 17. 电话号码的字母组合 | C++ 回溯算法经典模板
c++·算法·leetcode
计算机安禾7 小时前
【数据结构与算法】第36篇:排序大总结:稳定性、时间复杂度与适用场景
c语言·数据结构·c++·算法·链表·线性回归·visual studio
unicrom_深圳市由你创科技7 小时前
做虚拟示波器这种实时波形显示的上位机,用什么语言?
c++·python·c#
无限进步_7 小时前
【C++】电话号码的字母组合:从有限处理到通用解法
开发语言·c++·ide·windows·git·github·visual studio
C++ 老炮儿的技术栈7 小时前
GCC编译时无法向/tmp 目录写入临时汇编文件,因为设备空间不足,解决
linux·运维·开发语言·汇编·c++·git·qt
橘颂TA7 小时前
【笔试】算法的暴力美学——牛客 NC213140 :除2!
c++·算法·结构与算法