[数论系列] 素数篇

本章介绍关于素数的一些数论,限于篇幅不给出证明,需要证明的朋友自行相关证明。

什么是素数?只能被自己和1整除的数就是素数。

利用这个性质我们很容易得到下面的素数判断方法。

bool isPrime(int x){
    if(x==1)return 0;
    for(int i=2;i*i<=x;i++)
        if(x%i==0)return 0;
    return 1;
}

这里解释一下为什么是i*i<=x,i*i

想一想,如果我们枚举到sqrt(x)都没有找到可以被它整除的数,后面也就不可能有可以被它整除的数了,因为一个>sqrt(x)的数要是被x整除了,它的商肯定是sqrt(x)的约数也是不可能有的。

这种判断方法的时间复杂度是O(sqrt(n))的,空间复杂度是O(1)的。

再给出一个判断方法,这个方法的时间复杂度大概是O(sqrt(n)/3)的,空间复杂度也是O(1)。

bool isPrime(int x){
    if(x==1)return false;
    if(x==2||x==3)return true;
    if(x%6!=1&&x%6!=5)return false;
    for(int i=5;i*i<=x;i+=6)
        if(x%i==0||x%(i+2)==0)return false;
    return true;
}

证明被我吃了。

然后就是几种素数的筛法了。我们规定下文中讨论的[]为向下取整。

首先是著名的埃筛,Eratosthenes筛法。

埃筛基于这样一个想法:对于一个数x,它的倍数2x,3x,4x,5x...都不是质数。

于是,我们从2开始从小到大扫描每个数x,把它的倍数2x,3x,4x,...,[N/x]*x标记为合数

当扫描到一个数时,若它未被标记为合数,则它就不能被2~x-1中的任何数整除,它就是质数。

但是我们会发现,埃筛会重复标记一个数。比如8,它会被2标记,还会被4标记,这样影响了效率。

于是我们考虑优化,对于每个数,从x^2开始把x^2,(x+1)*x,...,[N/x]*x标记为合数。

给出代码:

int comp[maxn],prime[maxn];
//合数标记(composite),素数标记
void Eratothenes(int n){//筛到哪里
   for(int i=2;i<=n;i++){ if(comp[i])continue; prime[i]=1;//i是质数 for(int j=i;j<=n/i;j++)comp[i*j]=1; } }

优化后的埃筛的时间复杂度是O(nloglogn),接近线性,而且很好写,推荐熟记。

那有没有线性筛呢,有,但是个人认为,会埃筛就够了,没必要为了卡常写到线性。

想了解的可以自行百度。

接下来给出一些定理,还是一样,不证。

1. 唯一分解定理

若整数x>=2,则x一定可以以唯一的形式表示成若干个素数的乘积。

可以写作:x=p1^c1*p2^c2*p3^c3*...*pm^cm。

其中,ci均为正整数且pi均为素数,满足p1

2. 威尔逊定理

没啥用的定理,若p为素数,则(p-1)! ≡ 1(mod p)。

3. 威尔逊定理的逆定理

若对于某一正整数p,有(p-1)! ≡ -1(mod p),则p为素数。

3. 费马定理

若p为素数,x为正整数,且x和p互质,则x^(p-1) ≡ 1(mod p)。

4. 费马小定理

若p为素数,则x^p ≡ x(mod p)。

 

还有一些东西:( ﹁ ﹁ ) ~→待填坑  

 

你可能感兴趣的:([数论系列] 素数篇)