素数筛的用处还是蛮多的,有很多和素数有关的题都要用到素数筛,所以有一个高效的筛法自然是非常好的吖,普通筛法(暴力筛法)就不说了,因为有了高效的也没人在会用普通筛法了吧。
线性素数筛是用每一个合数的最小的质因数筛掉它,所以时间复杂度保证是线性的。
模板:https://www.luogu.org/problemnew/show/P3383
代码:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int n,m; 5 bool vis[10000003]; 6 int prime[1000003]; 7 int cnt; 8 int main() 9 { 10 scanf("%d%d",&n,&m); 11 vis[0]=vis[1]=1; 12 for(int i=2;i<=n;++i) 13 { 14 if(!vis[i])prime[++cnt]=i; 15 for(int j=1;j<=cnt&&i*prime[j]<=n;++j) 16 { 17 vis[i*prime[j]]=1; 18 if(i%prime[j]==0)break; 19 } 20 } 21 while(m--) 22 { 23 int x; 24 scanf("%d",&x); 25 if(!vis[x])printf("Yes\n"); 26 else printf("No\n"); 27 } 28 return 0; 29 }
还有一个叫做区间素数筛的东西,窝也是前几天才知道的,不过不是线性的,或许有线性的写法吧,不太会,但是复杂度也不是很高。
1 #include<iostream> 2 #include<cstdio> 3 #define ll long long 4 using namespace std; 5 const int maxn=1000005; 6 bool b1[maxn],b2[maxn]; 7 ll prime[maxn]; 8 ll cnt;//区间素数筛的原理:(a,b)区间的合数的最小质因数一定小于sqrt(b), 9 //所以把2到sqrt(b)的素数筛出来,蓝后,用他们把他们在a到b的倍数筛出来 10 int main() 11 { 12 ll a,b; 13 scanf("%lld%lld",&a,&b);b++; 14 for(ll i=0;i*i<b;++i)b2[i]=1; 15 for(int i=0;i<b-a;++i)b1[i]=1; 16 for(ll i=2;i*i<b;++i) 17 { 18 if(b2[i]) 19 { 20 for(ll j=2*i;j*j<b;j+=i)b2[j]=0; 21 for(ll j=max(2ll,(a+i-1)/i)*i;j<b;j+=i)b1[j-a]=0; 22 } 23 } 24 for(ll i=0;i<b-a;++i) 25 if(b1[i])prime[cnt++]=a+i; 26 printf("%d\n",cnt); 27 }
原文地址:https://www.cnblogs.com/yuelian/p/8758876.html
时间: 2024-11-05 13:36:05