写这个类型博客的目的就是想总结一下某个专题的知识点,方便以后比赛前复习,由于太菜,如有错误,还请斧正。

首先讲一下求素数筛的几个算法

一、循环暴力法(O(n*sqrt(n)))

二、埃氏筛(O(nloglogn))对于数据范围较小的可以用,写着方便

void isprime(int n)
{
    for(int i=2;i<=n;i++)
    {
        if(!vis[i]) prime[x++]=i;
        for(int j=2;j*i<=n;j++)
        {
            vis[i*j]=true;
        }
    }
}

三、线性筛(欧拉筛)(O(n))

void oulasai(int n)
{
    for(int i=2;i<=n;i++)
    {
        if(!vis[i]) prime[x++]=i;
        for(int j=0;j<x;j++)
        {
            if(i*prime[j]>n) break;
            vis[i*prime[j]]=true;
            if(i%prime[j]==0) break;
        }
    }
}

四、米勒罗宾素数检测(基于随机算法的筛法,不稳定)

摘自:https://www.cnblogs.com/SinGuLaRiTy2001/p/6591414.html

#include<cstdlib>
#include<ctime>
#include<cstdio>
using namespace std;
const int count=10;
int modular_exp(int a,int m,int n)
{
    if(m==0)
        return 1;
    if(m==1)
        return (a%n);
    long long w=modular_exp(a,m/2,n);
    w=w*w%n;
    if(m&1)
        w=w*a%n;
    return w;
} 
bool Miller_Rabin(int n)
{
    if(n==2)
        return true;
    for(int i=0;i<count;i++)
    {
        int a=rand()%(n-2)+2;
        if(modular_exp(a,n,n)!=a)
            return false;
    }
    return true;
}
int main()
{
    srand(time(NULL));
    int n;
    scanf("%d",&n);
    if(Miller_Rabin(n))
        printf("Probably a prime.");
    else
        printf("A composite.");
    printf("\n");
    return 0;
}

以上是常用的几种素数筛法

下面呢就来讲讲素数的一些性质

1.哥德巴赫猜想:任何一个大于4的偶数可以拆分成两个质数,任何一个大于7的奇数可以拆分成三个质数

2.如果2^x-1是素数,那x一定也是素数

3.所有大于10的质数中,个位数只有1,3,7,9

4.任何大于3的素数都可以表示为形式

5.所有大于2的素数都可以唯一地表示成两个平方数之差​​​​

6.当n为大于2的整数时,2^n+1和2^n-1两个数中,如果其中一个数是素数,那么另一个数一定是合数

当然素数的应用还有很多

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

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); 
            }
        }
    }
}

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

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); 
        }
    }
}

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

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;
                }  
            }
        }
    }
}

可能以后还会有加减