质数
1.质数
若对于一个大于 的正整数 ,有:
。
则称此数为质数(素数),否则此数为合数。
判定一个质数的方法之试除法:检查 之间的所有数是否能整除 。
bool check(int x) {
int cnt=sqrt(x);
for(int i=2;i<=cnt;++i) {
if(x%i==0) return false;
}
return true;
}
找 之间所有的质数:筛法。
暴力
对 的所有数判断是否是质数。
时间复杂度 。
朴素筛法
扫描 ,标记 以内所有的倍数,若当前没被标记则为质数。
调和级数知时间复杂度约为 。
埃拉托斯特尼筛法(埃氏筛)。
考虑优化上述筛法,发现只要标记质数的倍数就行。
并且由于 的数只需扫描 的数即可全部标记。
时间复杂度趋近于 。
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;
}
}
找大于 的最小的质数/小于 的最大的质数:
筛出符合范围的所有质数,再二分查找。
但真的很优秀吗?若至算法一个!
素数密度:在 中约有 个质数,即每 个数中大约有一个质数。
根据性质,我们直接暴力向前/后扫,试除法判断扫到的数是不是质数。
时间复杂度为 。
区间筛法
给定 ,求区间 以内的所有质数。
.
暴力筛 以内所有质数不现实。
发现 以内的所有数只需用埃氏筛标记 中的质数即可将质数全部筛出。
所以用偏移量数组,按照普通埃氏筛即可。
复杂度 ,其中 。
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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具