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

数论专题(1)——素数

时间:2018-06-30 12:41:03      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:cst   name   grub   splay   开始   pen   check   避免   技术   

      数论专题(1)——素数

 

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

    根据定义,可以用以下程序来判断一个数是否为素数

bool prime(int x) {//判断x是否为质数,时间复杂度为O(n)
    if(x <= 1) return false; 
    for(int i = 2; i < x; i ++)
        if(x % i == 0) return false;
    return true;
}

 

    接下来要加速了哦

bool prime2(int x){  //判断是否为质数,时间复杂度为O(sqrt(n)) 
    if(x <= 1) return false; 
    for(int i = 2; i <= sqrt(x + 0.5); i ++)  //0.5是防止根号的精度误差 
        if(x % i == 0) return false;
    return true;

    //另一种写法,可避免根号的精度误差 
    if(x <= 1) return false; 
    for(int i = 2; i * i <= x; i++)
        if(x % i == 0) return false;
    return true;
}

 

    虽然已经挺快的了,但是如果 n 比较大的话就不好玩了

    so... 接下来我们要讲一种更快的算法——埃拉托斯特尼筛法(咦~,好长),那就简称埃氏筛法吧

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

void init() {  //时间复杂度O(nloglogn) 我也不知道怎么算出来的 2333
    for(int i = 2; i < N; i++) prime[i] = true;
    for(int i = 2; i * i < N; i++)
        if(prime[i])
            for(int j = i * i; j < N; j += i)  //因为之前的都判断过了,所以从i*i开始就可以了 
                prime[j] = false;
}

int main() {
    scanf("%d", &N);
    init();
}

 

    线性筛法(欧拉筛法)

  保证每个合数只会被它的最小质因数筛去,因此每个数只会被标记一次,所以时间复杂度是O(n)

void prime() {
    for(int i = 2; i < n; i++) {
        if(!check[i]) prime[tot++] = i;
        for(int j = 0; j < tot; ++j) {
            if(i * prime[j] > n) break;
            check[i * prime[j]] = 1;
            if(i % prime[j] == 0) break;
        }
    }
}

 

  基于埃式筛法的原理,我们可以用它干很多事,比如:

技术分享图片
#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<cstdio>
#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();
}
预处理每个数的质因数分解

 

  推荐博客(专门讲素数的哦):https://www.cnblogs.com/grubbyskyer/p/3852421.html

 

数论专题(1)——素数

标签:cst   name   grub   splay   开始   pen   check   避免   技术   

原文地址:https://www.cnblogs.com/v-vip/p/9246386.html

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