素数(线性筛法)

题目描述

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

相关推荐
MZ_ZXD00112 分钟前
springboot旅游信息管理系统-计算机毕业设计源码21675
java·c++·vue.js·spring boot·python·django·php
A星空1231 小时前
一、Linux嵌入式的I2C驱动开发
linux·c++·驱动开发·i2c
凡人叶枫2 小时前
C++中智能指针详解(Linux实战版)| 彻底解决内存泄漏,新手也能吃透
java·linux·c语言·开发语言·c++·嵌入式开发
会叫的恐龙2 小时前
C++ 核心知识点汇总(第六日)(字符串)
c++·算法·字符串
小糯米6012 小时前
C++顺序表和vector
开发语言·c++·算法
独望漫天星辰2 小时前
C++ 多态深度解析:从语法规则到底层实现(附实战验证代码)
开发语言·c++
王老师青少年编程3 小时前
2024年信奥赛C++提高组csp-s初赛真题及答案解析(阅读程序第3题)
c++·题解·真题·csp·信奥赛·csp-s·提高组
凡人叶枫3 小时前
C++中输入、输出和文件操作详解(Linux实战版)| 从基础到项目落地,避坑指南
linux·服务器·c语言·开发语言·c++
CSDN_RTKLIB3 小时前
使用三方库头文件未使用导出符号情景
c++
rainbow68895 小时前
Linux文件描述符与重定向原理
c++