1.普通的线性筛
原理:素数的倍数是合数,合数的倍数还是合数,把所求区间的合数全都去掉了,剩下的就是素数了
模板:
#include
#include
#include
#include
#define maxx 20 //maxx是几就表明要求的是 : 从一到几这个范围内的素数
using namespace std;
int su[maxx];//这里面存放的是素数
int book[maxx + 5];//su:素数集合,book[]标记是否为素数,注意一定要加x否则数组溢出特别难查出来
int cnt;//cnt代表的是在su[]这个数组中,因为要往里塞题给范围内的素数嘛,所以这个cnt就是塞素数时的下角标,当然了,还充当输出时的输出上界
void xianxingshai()
{
cnt=1;
memset(book,-1,sizeof(book));
for(int i=2;i
2.快速线性筛法
这里有一个大佬的博客https://blog.csdn.net/yangyuhao0408/article/details/50956143(就只看他快速线性筛法那部分就行,和下面这个的代码和思路是一样的,下面这个代码里还有解释)
模板:
#include
#include
#include
#include
using namespace std;
#define maxx 200 //maxx是几就表明要求的是 : 从一到几这个范围内的素数
long long prime[maxx+5];//这个集合中存的是质数的集合
long long num_prime;//num_pirme记录素数个数
int book[maxx];//book[]为-1是素数,为0是合数
void quick_su()
{
memset(book,-1,sizeof(book));
num_prime=0;
book[0]=book[1]=0;
for(long long i=0;i<=maxx;i++)
{
if(book[i]==-1)
{
prime[num_prime++]=i;
}
for(long long j=0;j
就像:
质数 2可以把4标记成合数 此时 质数集合有 :2
质数 3可以把 6,9 标记成合数 此时 质数集合有 :2,3
质数 5可以把10,15,25标记成合数 此时 质数集合有 :2,3, 5
质数 7可以把 14,21,35,49 标记成合数 此时 质数集合有 :2,3, 5, 7
质数 11可以把 22 , 33 , 55 , 77 , 121 标记成合数 此时 质数集合有 :2,3, 5, 7 ,11
以质数11 标记的合数为例:期中22,33,55,77其实都可以在之前用质数2,3,5,7标记掉
但是,如果之前标记了,现在在标记一遍会重复,所以用 if( !(i%prime[j]) ) break; 的语句来限制用以避免重复。
那么为什么这条语句可以避免重复呢?
因为一个定理:任何一个合数都可以写成几个质数相乘的形式
既然要标记的合数可以被其他更大的质数标记,那么,现在的质数只需要把自己范围内的合数标记了,其他指数范围内需要去标记的合数就没必要标记了:即 break。