在做数论题过程中,素数出现的频率很高,在基础题和中档题甚至很多高难度的题里面都很常见,这篇博客就来对素数及其使用做一个小小的总结
素数
首先,我们应该明确,素数的定义:
素数(prime number)又称质数,有无限个。素数定义为在大于1的自然数中,除了1和它本身以外不再有其他约数的数称为素数。
素数个数估计
既然素数有无限多个,那么n以内的素数有多少个呢?
可以通过如下方式来估计n以内的素数个数
素数个数估计:π(n)≈x/ln(n)
筛素数
知道了有这么多的素数,那我们如何得到素数呢?
直接一个一个遍历判断显然是不可取的,在竞赛中,我们一般采用打素数表的方法来解决这个问题,不知道哪位高人给打素数表起了筛素数这个名字,个人感觉十分贴切。筛法有很多,这里我只介绍一下时间效率最高的欧拉筛法,请看代码
const int MAXN = 10000000 + 10;
bool is_prime[MAXN];//素数筛,true表示该数为素数
int prime[MAXN];//素数表,这里面存了MAXN以内的所有素数
int tol;//素数个数统计
void PrimeTable(){
//初始化
memset(is_prime,true,sizeof(is_prime));
tol=0;
//从最小的素数2开始筛
for(int i=2;i<MAXN;i++){
//如果是素数就加入素数表中
if(is_prime[i]) prime[tol++]=i;
//进行筛素数操作
for(int j=0;j<tol;j++){
if(i*prime[j]>MAXN)break;
//把当前数字与素数表中的每个数字的乘积全部筛掉(这些因为有其他因子了,所以不可能是素数)
is_prime[i*prime[j]]=false;
//这里很关键,它保证了每一个合数只被筛一遍(大家可以在纸上模拟一下这个过程,就会有深刻的理解)
if(i%prime[j]==0)break;
}
}
}
素数的应用
大数据小区间筛素数个数
模拟筛法筛区间内素数个数,先打表,再根据表进行筛素数操作
typedef long long ll;
const int MAXN = 1000000+10;
bool is_prime[MAXN];//true的为合数,false的为素数
int prime[MAXN/10];//存素数
bool num[MAXN];
int tol;
void find_prime(){
memset(is_prime,false,sizeof(is_prime));
tol=0;
is_prime[1]=