数论初步之素数判断

基本数论-素数判断

 一、暴力求解

  1、一个共识

         x = a*b且x = sqrt(x)*sqrt(x) => a==b==sqrt(x)或者a<sqrt(x) 且 b > sqrt(x),即要么a==b要么一个大于根号x一个小于根号x

     且a = x/b,那么我们只用判断小于sqrt(x)的数是否可以整除x即可。         

  2、暴力求法(O(n^(2/3)))

                

bool isPrime(int x){
for(int i=2;i<=sqrt(x);i++){
if(x%i==0) return false;
}
return true;
}

void getPrime(int x){
for(int i=1;i<=x;i++){
if(isPrime(i)) cout<<i;
}
}

  3、素数普通筛选(n*log(n))

    思想:任何一个素x = 素数*一个数,那么我们可以在找到一个素数的时候,再花n/i的时间去把现在可以确定不是素数的数给标记出来。

    如:已知2是一个素数那么:2,4,6,8,10,12...2*i都不是素数。

    那么时间复杂度为:n/2+n/3+n/5+......+n/p,p为小于n的素数那么渐进时间复杂度为O(n*log(n))

void getPrime(int x,int* primes){
    for(int i=2;i<=x;i++){
        if(primes[i]==0){
            for(int j=2;j*i<=x;j++)
                primes[j*i] = 1;
        }
    }
}

  4、素数筛选之线性筛选(o(n))

    由3我们可以知道,任何一个数字都可以有一个素数乘一个数得到。比如2是素数那么4,6,8,10,12,14,16....2*i都不是素数了,比如3是素数那么6,9,12,15...3*i都不是素数了,我们

    可以看出在我们标记不是素数的时候6,12等在2中标记过,在3中也被标记过这样一来就多了很多重复的操作,那么怎么去优化呢?

    我们最容易想到的就是在int j这个循环中加入,prime[j*i]!=1这个标志,就可以很容易的跳过多余的标记,那么我们总共标记了n个元素所以时间复杂度为O(N).

    

void getPrimeLine(int x,int* primes){
    for(int i=2;i<=x;i++){
        if(primes[i]==0){
            for(int j=2;j*i<=x&&primes[j*i]!=1;j++)
                primes[j*i] = 1;
        }
    }
}

   或者我们可以根据当前的已知的素数来标记如已知 1,2,3,5现在第6次标记就用1,2,3,5分别乘2,3,4,5,6这样每次乘出来的也不一样最终也不会重复标记,因而时间复杂度为O(N)

  

 

posted @ 2018-12-30 16:07  coding==1?  阅读(330)  评论(0编辑  收藏  举报