质数

1.质数

若对于一个大于 1 的正整数 x,有:

1<y<x,yx

则称此数为质数(素数),否则此数为合数

判定一个质数的方法之试除法:检查 2n 之间的所有数是否能整除 n

bool check(int x) {
	int cnt=sqrt(x);
	for(int i=2;i<=cnt;++i) {
		if(x%i==0) return false;
	}
	return true;
}

1n 之间所有的质数:筛法

暴力

1n 的所有数判断是否是质数。

时间复杂度 O(nn)

朴素筛法

扫描 1n,标记 n 以内所有的倍数,若当前没被标记则为质数。

调和级数知时间复杂度约为 O(nlogn)

埃拉托斯特尼筛法(埃氏筛)

考虑优化上述筛法,发现只要标记质数的倍数就行。

并且由于 1n 的数只需扫描 1n 的数即可全部标记。

时间复杂度趋近于 O(nloglogn)

int vis[N],n;
vector<int>prime;
for(int i=2;i*i<=n;++i) {
	if(vis[i]) continue;
	for(int j=i*i;j<=n;j+=i) vis[j]=1;
}
for(int i=1;i<=n;++i) if(!vis[i]) prime.push_back(i);

时间复杂度证明。

线性筛法(欧拉筛)

再次考虑优化,发现会重复标记很恶心。

考虑如何仅标记一次,直接被最小质因子标记一次即可。

具体见注释。

int v[N],n;
vector<int>prime;
for(int i=2;i<=n;++i) {
	if(!v[i]) v[i]=i,prime.push_back(i);//是质数。 
	for(int p:prime) {
		if(p*i>n||v[i]<p) break;//超过范围或者有更小质因子。 
		v[p*i]=p;
	}
}

找大于 x 的最小的质数/小于 x 的最大的质数:

筛出符合范围的所有质数,再二分查找。

但真的很优秀吗?若至算法一个!

素数密度:在 1n 中约有 nlnn 个质数,即每 lnn 个数中大约有一个质数。

根据性质,我们直接暴力向前/后扫,试除法判断扫到的数是不是质数。

时间复杂度为 O(nlogn)

区间筛法

Q: 给定 l,r,求区间 [l,r] 以内的所有质数。

l,r1e9,rl1e6.

暴力筛 r 以内所有质数不现实。

发现 [l,r] 以内的所有数只需用埃氏筛标记 1r 中的质数即可将质数全部筛出。

所以用偏移量数组,按照普通埃氏筛即可。

复杂度 O(mloglogm),其中 m=rl

void Eratosthenes(ll n){
	for(ll i=2;i*i<=n;i++)
		for(ll j=(l+i-1)/i*i;j<=n;j+=i)
			if(j!=i)b[j-l]=0;
}
int main() {
	scanf("%lld%lld",&l,&r);
	Eratosthenes(r);
	for(int i=l;i<=r;i++)
        if(b[i-l]) ans++;
    ans-=max(2-l,0);
	printf("%lld\n",ans);
	return 0;
}
posted @   cannotmath  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示