码迷,mamicode.com
首页 > 其他好文 > 详细

ACM数论之旅1---素数(万事开头难(>_<))

时间:2018-04-09 13:12:06      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:include   时间复杂度   数论   复杂度   合数   判断   lse   定义   color   

素数,又叫质数,定义是除了1和它本身以外不再有其他的因数

我们通过这个定义,可以写如下程序判断一个数是不是质数

bool prime(int x){//判断x是不是质数,是返回true,不是返回false 
    if(x <= 1) return false; 
    for(int i = 2; i < x; i ++){
        if(x % i == 0) return false;
    }
    return true;
}

这个程序的时间复杂度是O(n),也是最原始的方法,但是可以优化到o(√n)

快速筛法(埃式筛法):

埃筛--------------埃拉托斯特尼筛法,或者叫埃氏筛法

 

原理:如果找到一个质数,那么这个质数的倍数都不是质数

 

比如2是质数,那么4,6,8,10,12...都不是质数

然后看3是质数,那么6,9,12,15,18,21...都不是质数

然后看4,4已经被2标记为合数了,所以跳过

然后看5......这样一直筛下去

时间复杂度是o(n logn logn)

#include<cstdio>
const int N = 100000 + 5;
bool prime[N];
void init(){
    for(int i = 2; i < N; i ++) prime[i] = true;//先全部初始化为质数 
    for(int i = 2; i < N; i ++){
        if(prime[i]){//如果i是质数 
            for(int j = i*i; j < N; j += i){//从i的两倍开始的所有倍数 
                prime[j] = false; 
            }
        }
    }
}
int main(){
    init();
}

 

 

好戏都是要留到最后的????确实还有O(n)的做法

这个算法名字叫线筛

这个方法可以保证每个合数都被它最小的质因数筛去

所以一个数只会经过一次

时间复杂度为O(n)

 

其实loglogn非常小,把埃筛看成线性也无妨,毕竟它比线筛好写

#include<cstdio>
const int N = 100000 + 5;
bool prime[N];//prime[i]表示i是不是质数 
int p[N], tot;//p[N]用来存质数 
void init(){
    for(int i = 2; i < N; i ++) prime[i] = true;//初始化为质数 
    for(int i = 2; i < N; i++){
        if(prime[i]) p[tot ++] = i;//把质数存起来 
        for(int j = 0; j < tot && i * p[j] < N; j++){
            prime[i * p[j]] = false;
            if(i % p[j] == 0) break;//保证每个合数被它最小的质因数筛去 
        }
    }    
}
int main(){
    init();
}

 

基于埃筛的原理,我们可以用它干很多事

比如预处理每个数的所有质因数

#include<cstdio>
#include<vector>
using namespace std;
const int N = 100000 + 5;
vector<int > prime_factor[N];
void init(){
    for(int i = 2; i < N; i ++){
        if(prime_factor[i].size() == 0){//如果i是质数 
            for(int j = i; j < N; j += i){
                prime_factor[j].push_back(i); 
            }
        }
    }
}
int main(){
    init();
}

比如预处理每个数的所有因数

#include<cstdio>
#include<vector>
using namespace std;
const int N = 100000 + 5;
vector<int > factor[N];
void init(){
    for(int i = 2; i < N; i ++){ 
        for(int j = i; j < N; j += i){
            factor[j].push_back(i); 
        }
    }
}
int main(){
    init();
}

比如预处理每个数的质因数分解

#include<vector>
using namespace std;
const int N = 100000 + 5;
vector<int > prime_factor[N];
void init(){
    int temp;
    for(int i = 2; i < N; i ++){
        if(prime_factor[i].size() == 0){
            for(int j = i; j < N; j += i){
                temp = j;
                while(temp % i == 0){
                    prime_factor[j].push_back(i);
                    temp /= i;
                }  
            }
        }
    }
}
int main(){
    init();
}

 

ACM数论之旅1---素数(万事开头难(>_<))

标签:include   时间复杂度   数论   复杂度   合数   判断   lse   定义   color   

原文地址:https://www.cnblogs.com/xuyanqd/p/8758908.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!