洛谷p3383线性筛素数
#include <iostream>
#include <stdio.h>
using namespace std;
/*
需要两个数组
一个用来判断是否是质数,另一个用来存放已经判断好的质数
*/
bool is_prime[100000010];int prime[1000010];
int main()
{
std::ios::sync_with_stdio(0);
int n,q;
cin>>n>>q;
int index=1;//下标
for(int i=2;i<=n;i++)
{
if(is_prime[i]==0)//是质数
{
prime[index]=i;
index++;
}
for(int j=1;j<index&&i*prime[j]<=n;j++)
{
is_prime[i*prime[j]]=1;
if(i%prime[j]==0) break;//这里理解了很久,仅对这里解释,方便自己复习
}
}
int temp;
for(int i=1;i<=q;i++)
{
cin>>temp;
cout<<prime[temp]<<endl;
}
return 0;
}
利用的原理是一个合数可拆成一个最小质数和另一个数的积
只要我们保证一直是这个数的最小质数和另一个数相乘来表示这个合数来进行判断就不会重复
因为一个数的最小质数是唯一确定的
当确定了一个乘数之后,那么另一个乘数也确定了
就不会拆分多次判断的情况
如果一个数是被拆分成最小质数和另一个质数相乘,那么这个数一定不会有第二种拆分方式,不会有重复的情况。
但是当一个数是被拆分成最小质数和一个合数相乘,那么这个数不止一种拆分方式,如果不加以限制就会造成重复判断。
比如12
12的最小质数是2
在12之前已经被判断出的质数有2,3,5…
将12与它们依次相乘判断合数
12×2(当这个合数的最小质数出现时,如果再和后面的质数相乘,那么实际上就是最小质数不变对数进行拆分,但实际上这个循环里我们想进行的操作是最小质数改变的拆分,一直把prime[]当成最小质数在处理,实际上已经不是了
)
12×3(当后面对18进行操作时 与18×2重复判断)
12×5…所以为了避免重复判断,我们在该数的最小质数出现后,立刻跳出循环。