筛素数
普通筛素数#
素数的因数只有1和它本身
根据这个定义,有个筛素数这种方法
当我们想找小于30的素数的时候,可以从小到大遍历
当遍历到2的时候,2就是素数,而2的倍数将被筛去
剩余最小的数的是3,3就是素数,而3的倍数将被筛去
剩余最小的数是5(4已被筛去),再筛去5的倍数
直到最后,每次最小的数就是素数,而它的倍数将被筛去
每次找到的最小数,因为没有被筛去,说明前面没有他的因数,说明最小数一定是素数且素数一定不会被筛掉
c++代码#
#include "iostream"
#include "cstring"
using namespace std;
int main(int argc, char const *argv[])
{
int s=0;
bool IsPrime[100];
memset(IsPrime,1,sizeof(IsPrime));
for(int i=2;i<100;i++){
if(IsPrime[i]){
cout << i << ' ';
for(int j=2;j*i<100;j++){
IsPrime[i * j]=false;
s++;
}
}
}
cout << endl << s;
return 0;
}
线性筛素数#
在前面的筛素数方法中会产生重复筛的问题,比如12在2时筛了一次,在3时又筛了一次,这样就大大降低了效率.
因此我们需要一种方法使得每个合数只被筛一次
可以看出
12=43
4=22
因此12=223=2*6
也就是说每个合数都可以被分解成唯一的最小的质数和另一个数的乘积的形式,因此12应当在2时被晒而不是3
和上面的普通筛不同,普通筛是筛去素数的k倍(k=2,3,4,5...)
线性筛是筛去i的素数倍,此时就可以判断,如果i%prime[j]==0
此时应当break
否则就会重复筛
例如:
当i=8时,i%prime[0]=8%2==0
,此时筛去2*8=16
后应当break
如果继续筛3*8=24
因为8可以被2整除,因此24=8*3=12*2
,24应当在i=12时被筛
因此我们建立两个数组,prime[]
保存素数,isNotPrime[i]
指示i是否是素数,num_prime
保存素数的个数
C++代码#
#include <iostream>
using namespace std;
const int N = 100;
int prime[N] = {0},num_prime = 0;
int isNotPrime[N] = {1, 1};
int main()
{
for(int i = 2 ; i < N ; i ++){
if(! isNotPrime[i]) //i是素数
prime[num_prime ++]=i;
//遍历小于i的所有素数
for(int j = 0 ; j < num_prime && i * prime[j] < N ; j++){
isNotPrime[i * prime[j]] = 1; //筛去i的素数次倍
if( !(i % prime[j] ) ) //i可以被prime[j]*k代替,可以留到i=prime[j+1]*(i/prime[j])时再筛
break;
}
}
for(int i=0;i<num_prime;i++) cout << prime[i] << ' ';
return 0;
}
作者: lepeCoder
出处:https://www.cnblogs.com/lepeCoder/p/scanPrime.html
版权:本站使用「CC BY 4.0」创作共享协议,转载请在文章明显位置注明作者及出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一文彻底搞懂 MCP:AI 大模型的标准化工具箱
· 电商平台中订单未支付过期如何实现自动关单?
· 用 .NET NativeAOT 构建完全 distroless 的静态链接应用
· 为什么构造函数需要尽可能的简单
· 探秘 MySQL 索引底层原理,解锁数据库优化的关键密码(下)
· 短信接口被刷爆:我用Nginx临时止血
· 面试官:如果某个业务量突然提升100倍QPS你会怎么做?
· .NET 平台上的开源模型训练与推理进展
· 聊聊智商税:AI知识库
· Google发布A2A开源协议:“MCP+A2A”成未来标配?