找素数 (素数筛+离散化)

问题描述
  给定区间[L, R] , 请计算区间中素数的个数。
输入格式
  两个数L和R。
输出格式
  一行,区间中素数的个数。
样例输入
2 11
样例输出
5
题目异常简单,可是不是很好做,l和r的范围太大了,直接暴力一定会超时,可以借鉴素数筛的思路,用素数把合数筛去,区间内的最大数是r,所以可以做因子的素数一定不大于sqrt®,所以只用把小于sqrt®的所有素数全部筛出来,再用他们去筛区间内的数,有一个问题素数筛的时候要用到一个标记数组,可是r太大了,数组开不了那么大,但是有一个条件r-l<=1e6,所以可以把整个区间离散化到区间[0,r-l]就可以了。

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int inf=2147483647,N=1000010;
int l,r;
int prim[N],cnt;
bool st[N];
void init()//预处理出来所有的素数,线性筛模板
{
	for(int i=2;i<=sqrt(inf);i++)
	{
		if(!st[i]) prim[cnt++]=i;
		for(int j=0;prim[j]<=sqrt(inf)/i;j++)
		{
			st[prim[j]*i]=1;
			if(i%prim[j]==0) break;
		}
	}
}
int main()
{
	init();
	memset(st,0,sizeof st);
	cin>>l>>r;
	for(int i=0;i<cnt;i++)
	{
		for(int j=(l+prim[i]-1)/prim[i];j<=r/prim[i];j++)//j是区间[l,r]内的数存在的prim[i]的倍数,左端点向上取整,左端点向下取整
			if(j!=1)//倍数是1,所以这个数就是素数本身不能筛
				st[prim[i]*j-l]=1;
	}
	int ans=0;
	for(int i=0;i<=r-l;i++)
		ans+=!st[i];
	cout<<ans;
	return 0;
}

再来一道类似的题:https://www.acwing.com/problem/content/198/

原文地址:https://www.cnblogs.com/neflibata/p/12871758.html