Advertisement

基础数论算法(六) 素数的筛法与质因数分解

阅读量:

素数筛法

如果我们需要多次判断是不是素数时,比起无数次的枚举、测试,还是提前筛出一张素数表比较好


Eratosthenes筛法

一般情况下够用的筛法。复杂度nlnlnn,关键是不容易写错。还有别问我这个复杂度怎么算出来的。实现非常简单。

复制代码
    #include <iostream>
    #include <cstring>
    using namespace std;
    #define MAXN 1000001
    int main(){
    bool notprime[MAXN];
    memset(notprime,0,sizeof(notprime)); 
    notprime[1]=1;
    for(int a=2;a<MAXN;a+=(a==2?1:2))
        if(!notprime[a])  //如果不加的话复杂度nlnn 
            for(int k=2;a*k<MAXN;++k)
                notprime[k*a]=1;
    for(int i=1;i<MAXN;++i)
        if(!notprime[i])
            cout<<i<<endl;
    return 0;
    }

线性筛

又称欧拉筛,复杂度几乎是O(n),甚至直接看成O(n)即可。其秘诀就是保证每个数都是被自己最小的因子筛掉的。
它的实现是这样的:对i,分别筛掉i*prime[j],其中prime[j]表示所有小于i的素数的数组。如果prime[k]|i,则直接推出循环,因为该数一定会被其他数筛掉。
在数据比较大的时候,欧拉筛会明显占优势。缺点是容易写错。

复制代码
    #include <iostream>
    #include <cstring>
    #define MAXN 14
    using namespace std;
    bool notprime[MAXN];
    int prime[MAXN];
    int main(){
    notprime[1]=true;
    int count=0;
    for(int i=2;i<MAXN;++i){
        if(!notprime[i])
            prime[++count]=i;
        for(int j=1;j<=count;++j){
            if(prime[j]*i>MAXN) 
                break;
            notprime[prime[j]*i]=true;
            if(i%prime[j]==0)
                break;
        }
    }
    for(int i=1;i<MAXN;++i)
        if(!notprime[i])
            cout<<i<<endl;
    }

欧拉筛的原理我曾经想了一个上午也没有搞懂……所以实在不行就背代码吧。


质因数分解

分解质因数还是很有意义的一件事,实现起来也不算太难。

试除法

可以借助筛出的素数分解,这样会降些复杂度,这里就直接写不需要提前筛的算法了。

复制代码
    #include <iostream>
    #include <vector>
    using namespace std;
    typedef long long LL;
    int main(){
    LL a;
    cin>>a;
    vector<pair<LL,int> > v;
    vector<pair<LL,int> >::iterator vi;
    for(int i=2;i*i<=a;i+=(i==2?1:2)){
        if(a%i==0){
            int count=0;
            while(a%i==0)
                ++count,a/=i;
            v.push_back(make_pair(i,count));
        }
    }
    if(a!=1) v.push_back(make_pair(a,1));
    for(vi=v.begin();vi!=v.end();++vi)
        cout<<vi->first<<" "<<vi->second<<endl;
    }

Pollard算法

无论如何,我们都需要记住,这门科学是RP科学。因此,随机化算法一定是一个不可或缺的部分!
不过虽然这么说……我觉得NOIP大概用不到这玩意吧,反正我是完全没有看懂……如果想搞懂的话可以参考
http://www.cnblogs.com/jackiesteed/articles/2019910.html
http://qkxue.net/info/120352/Pollard-rho


全部评论 (0)

还没有任何评论哟~