数论专题——素数

Posted v-vip

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数论专题——素数相关的知识,希望对你有一定的参考价值。

      数论专题(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

 

以上是关于数论专题——素数的主要内容,如果未能解决你的问题,请参考以下文章

kuangbin数论专题记录

数论部分第一节:素数与素性测试详解

数论——素数

数论--素数

三 数论的编程实验

数论——HDU - 2136