有关素数的基础算法

之前因为各种原因没看数学相关问题,这回牛客网44练习赛打完或回头来看发现还是要看一下才行,不然有点摸不着头脑

1.素数判定

给定正整数n,请判断n是不是素数

bool is_prime(ll n)
{
    for (int i = 2; i*i <= n; i++)
        if (n%i==0) return false;
    return n!=1;
}

2.埃氏筛法

给定正整数n,请问n以内有多少个素数?

int prime[MAX_N]; //第i个素数 
bool is_prime[MAX_N+1]; //值为true表示为素数

//返回n以内的素数
int sieve(ll n)
{
    int p = 0;
    for (int i = 0; i <= n; i++) is_prime = true;
    //is_prime[0] = is_prime[1] = false;
    for (int i = 2; i<= n; i++) {
        if (is_prime[i]) {
            prime[p++] = i;
            for (int j = 2*i; j <= n; j += i) is_prime[j] = false;
        }    
    }
    return p;
} 

3.区间筛法

给定正整数a和b,请问区间[a,b)又多少个素数?

typedef long long ll;

bool is_prime[MAX_L];
bool is_prime_small[MAX_SORT_B];

//对区间[a,b)内的整数执行筛法
void segment_sieve(LL a,LL b)
{
    for(int i = 0; (LL)i*i < b; i++) is_prime_small[i]=true;
    for(int i = 0; i < b-a; i++) is_prime[i]=true;
     //利用0~len代表a~b的数
    for(int i = 2; (LL)i*i < b; i++) {
        if(is_prime_small[i]) {
            for(int j = 2*i; (LL)j*j < b; j += i) is_prime_small[j]=false; //筛[2,√b)
            for(LL j=max(2LL, (a+i-1)/i)*i ; j < b; j+=i) is_prime[j - a] =false;//筛[a,b)
            //j代表素数,j-a是将a~b变为0~b-a以便数组好存储
            //2LL是2的长整形形式,与其比较意思是j最少是i的两倍
            //((a+i-1)/i)*i得出的是(>=a && %i==0)离a最近的数,这里分子上a-1是个小细节 
            //其实也可以写成a%i==0?a:(a/i+1)*i
        }
    }
}
原文地址:https://www.cnblogs.com/wizarderror/p/10745749.html