[数论系列] 素数篇

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

什么是素数?只能被本身和1整除的数就是素数。spa

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

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<x转化一下就是i<=sqrt(x)。blog

想想,若是咱们枚举到sqrt(x)都没有找到能够被它整除的数,后面也就不可能有能够被它整除的数了,由于一个>sqrt(x)的数要是被x整除了,它的商确定是<sqrt(x)的,而咱们已经枚举过<=sqrt(x)的数了,里面没有,因此>sqrt(x)的约数也是不可能有的。ci

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

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

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;
}

证实被我吃了。class

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

首先是著名的埃筛,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<p2<...<pm

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)。

 

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

相关文章
相关标签/搜索