2025-02-02 12:13阅读: 23评论: 0推荐: 0

浅谈筛法

假期一到,随着竞赛集训结束,也是终于放假了!但是假期只有一半,但是还有竞赛作业...其中一项便是写4篇题解,本人也借此机会温习一下旧知识(绝对不是想水题解),第一篇就分享一下筛法,欢迎交流讨论!

引入


-例题

给定两个正整数\(n\),\(q\)然后询问\(q\)次,每次询问第\(m\)小的质数保证质数小于等于\(n\)

-思路

用数组把质数进行存储,再输出第\(m\)个便可以了,但是我们需要考虑时间空间限制,一般题暴力也可以,但有些题就想要让我们用线性筛。接下来进行讲解,供各位鉴赏。

埃氏筛


-原理

在遍历到某一个数字\(k\)时,如果\(k\)是质数,那么它的倍数(\(2*k\),\(3*k\)...\(n*k\))必然不是质数,若\(k\)不是质数,它必定被前面的某个质数排掉。

-核心代码

vector<bool> prime(n+1,true);//用数组存下0-n,默认每个数都是质数(true)
prime[0]=prime[1]=false;//0,1不是质数(fales)
for(int i=2;i*i<=n;++i){//遍历(Q1:为什么是i*i?)
	if(prime[i]){
		for(int j=i*i;j<=n;j+=i){//对这个质数的平方后的倍数排除(Q2:为什么从i*i开始?)
			prime[j]=false;//排除
		}
	} 
}

-Tips

Q1:

合数的性质:

如果 n 是合数,那么它至少有一个质因数 p 满足 p ≤ √n。

例如,n = 100,√100 = 10。如果 n 是合数,它至少有一个质因数 p ≤ 10。

Q2:

筛法的起始点:

对于质数 i,i 的倍数 \(i*2\), \(i*3\), ...,$ i*(i-1) $已经被更小的质数筛除了。

因此,直接从 j = i * i 开始筛除。

上代码


#include <bits/stdc++.h>
using namespace std;

int main() {
	int n,q,m;
	cin>>n>>q;
	vector<bool> prime(n+1,true);
	prime[0]=prime[1]=false;
	for(int i=2;i*i<=n;++i){
		if(prime[i]){
			for(int j=i*i;j<=n;j+=i){
				prime[j]=false;
			}
		} 
	}
	
	vector<int> primes;//存入质数
    for(int i=2;i<=n;++i){
        if(prime[i]) primes.push_back(i);
    }
	
	while(q--){//多次询问
		cin>>m;
		if(m>=1&&m<=primes.size()){
			cout<<primes[m-1]<<endl;
		}else{
			cout<<-1<<endl;
		}
	}
	
	
    return 0;
} 


题解++,任务--!

感谢观看!

本文作者:ccgc718

本文链接:https://www.cnblogs.com/ccgc718/p/18696762

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   ccgc718  阅读(23)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起