求有限区间内素数个数
求[l, r]这段区间中有多少素数
1 ≤ l ≤ r ≤ 10 ^6
一个显然的想法是利用for循环枚举[l, r]中的每一个数。然后利用朴素算法O(√X)进行判断。
整体复杂度O(N√N),不符合要求
#include<iostream> using namespace std; int r,l; int ans; int main(){ cin>>r>>l; for( int i=r ; i<=l ; ++i ){ if( n%i!=0 ){ ans++; } } cout<<ans; return 0; }
仍然考虑枚举判断每个数是否是素数,但我们这次从2开始判断。
考虑对于任意一个数x,不论x是否为素数,都有x*2,x*3,x*4...为合数。我们“筛”掉这些必然为合数的数。那么当我们枚举到i,i还没有被筛掉,那么i必然为素数。
时间复杂度O(NlogN)
#include<iostream> using namespace std; int r,l; int prime[1e6],c; bool num[1e6]; int ans; int main(){ cin>>r>>l; for( int i=2 ; i<=l ; ++i ){ if( !num[i] ) prime[++c]=i; if( i>=r && i<=l && !num[i] ) ans++; for( int j=1 ; i*prime[j]<=n && j<=c ; ++j ){ num[ i*prime[j] ] = 1; if( i%prime[j]==0 ) break; } } cout<<ans; return 0; }
T次询问,每次询问[l, r]中有多少素数
1 ≤ T ≤ 10^5, 1 ≤ l ≤ r ≤ 10 ^6
我们用ANSL,R来表示[l, r]中有多少素数,发现ANSL,R = ANS1,R - ANS1,L-1,
于是我们可以维护一个素数个数的前缀和Sum[i]表示[1, i]中有多少素数,每次询问就输出Sum[r] - Sum[l - 1]即可
#include<iostream> using namespace std; #define maxn 1000005 int sum[maxn],vis[maxn]; int t,l,r; void pre(){ for( int i=2 ; i<=maxn ; ++i ){ sum[i]=sum=[i-1]; if( !vis[i] ) sum[i]++; for( int j=i*2 ; j<=maxn ; j+=i ) vis[j]=1; } } int main(){ pre(); cin>>t; while( t-- ){ cin>>l>>r; cout<<sum[r]-sum[l]; } return 0; }