质数知识总结
质数
质数是指 只有两个正因数(1和它本身) 的自然数。
关于质数,主要有这 4 个知识。
质数的判断
时间复杂度 : 。
本来是要枚举 的,但是可以优化。
对于一个合数来说,肯定 有一个 的因数 。
为什么呢?
因为合数一定是由两个数(不为 1、本身)相乘得来的,而且众所周知:
。
如果其中一个因数 ,那么必有一个因数 。所以如果 x 为一个合数,那么一定可以找到一个 的因数,故可以判断素数。
代码
bool prime(long long x)//判定素数
{
if(x<2) return false;
for(long long i=2;i*i<=x;i++)
{
if(x%i==0)
{
return false;
}
}
return true;
}
为什么用 呢?
sqrt() 由二分答案实现,有复杂度,有误差,sqrt(x+0.5)可避免。在循环内使用会耗费大量时间。
质数的筛选以及个数
时间复杂度为:
在前面讲到,合数一定 有一个 的因数 。
那么一个质数 的倍数 是不是一定是个合数呢?
显然是的,因为 。
就可以根据这个思想引出埃氏筛。
代码
bool pri[1000010];
int prim[1000010];int cnt;
void cunchupri(int x)
{
pri[1]=1;
for(int i=1;i<=x;i++){
if(pri[i]==0) {
prim[++cnt]=i;
for(int j=2;j*i<=x;j++) pri[i*j]=1;
}
}
}
质因数分解
时间复杂度:
有些题目要求一个数的质因数,怎么办呢?
显然是通过短除法来求解,从小到大除就好。
但是有一个问题,如果从小到大除,除的那个数一定是个质数吗?其实是肯定的。一个合数一定是由几个质数相乘得来的,所以只要把其中质数先解决,就不会有合数出现。
这样做的话方法其实还是 的。回到质数的判断。
。
还是这个道理,最多只会出现一个 的合数。并且合数还会被分为几个质数,就相当于最多只会出现一个 的质数。此时就可以先把 的数全部筛掉。再把剩下质数的统计。
代码
int num[20],cnum[20],ccnt;//num质因数 cnum 某个质因数的个数 ccnt 总共不同质因子个数
void fj(long long x)//分解质因数
{
for(long long i=2; i*i<=x; i++)
{
if(x%i==0){
num[++ccnt]=i;
}
while(x%i==0)
{
cnum[ccnt]++;
x/=i;
}
}
if(x!=1)
{
num[++ccnt]=x;
cnum[ccnt]=1;
}
}
线性筛(欧拉筛)
void void Euler_sieve(int n) {
memset(isprime,true,sizeof(isprime));
prime[0]=0;//记录当前素数个数
for(int i=2;i<=n;i++) {
if(isprime[i])prime[++prime[0]]=i;//把素数保存到素数表prime中,并更新素数个数
for(int j=1;j<=prime[0]&&i*prime[j]<=n;j++) {
isprime[i*prime[j]]=false;//筛除i*prime[j]
if(i%prime[j]==0) break;
//当i中含有素因子prime[j]时中断循环,确保每个数只被它最小素因子筛除
}
}
}

浙公网安备 33010602011771号