Single prime number determination, prime number sieve method and interval prime number sieve method

code and comments

#include <cstdio>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;
/**
 * 素性测试O(√n)
 * 假设输入都是正数
*/
bool is_prime(int n){
    for(int i=2;i*i<=n;i++){
        if(n%i==0){
            return false;
        }
    }
    return n!=1;
}
/**
 * 约数枚举O(√n)
*/
vector<int> divisor(int n){
    vector<int> res;
    for(int i=1;i*i<=n;i++){
        if(n%i==0){
            //加入前半部分素数
            res.push_back(i);
            if(i!=n/i){
                //加入后半部分素数
                res.push_back(n/i);
            }
        }
    }
}
/**
 * 整数分解O(√n)
*/
map<int,int> prime_factor(int n){
    map<int,int> res;
    for(int i=2;i*i<=n;i++){
        //如果n是合数
        while(n%i==0){
            //从2开始统计每一个素数因子的个数
            ++res[i];
            n/=i;
        }
    }
    if(n!=1){
        res[n]=1;
    }
    return res;
}
int main(void){
    map<int,int> m=prime_factor(24);
    map<int,int>::iterator ite=m.begin();
    while(ite!=m.end()){
        cout << "因子" << ite->first << "的个数是" << ite->second <<  endl;
        ite++;
    }
}
#include <cstdio>
#include <iostream>
using namespace std;
#define MAX_N 100000000
typedef long long ll;
/**
 * 保存素数
*/
int prime[MAX_N];
/*
 * 标记is_prime[i]是否是素数,用于模拟删除
*/
bool is_prime[MAX_N+1];
/**
 * 区间筛法大数组[a,b)
*/
bool is_prime_large[MAX_N];
/**
 * 区间筛法小数组[2,√b)
*/
bool is_prime_small[MAX_N];
/**
 * 素数筛法返回n以内素数的个数,并将素数保存在prime数组中
*/
int sieve(int n){
    //素数个数
    int p=0;
    //初始化
    for(int i=0;i<=n;i++){
        is_prime[i]=true;
    }
    //0,1不是素数,删去
    is_prime[0]=is_prime[1]=0;
    //遍历
    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;
}
/**
 * 区间素数筛法,返回区间[a,b)内的素数个数
 * 先分别做好[2,√b)的表和[a,b)的表,然后从[2,√b)的表中筛得素数的同时,
 * 也将其倍数从[a,b)的表中划去,最后剩下的就是[a,b)内的素数了
*/
ll 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_large[i]=true;
    }
    for(int i=2;(ll)i*i<b;i++){
        if(is_prime_small[i]){
            //筛[2,√b)
            for(int j=2*i;(ll)j*j<b;j+=i){
                is_prime_small[j]=false;
            }
            //筛[a,b)
            //(a+i-1)/i)*i是符合>=a且是i的倍数的最小的数
            //因为除以i会舍弃掉余数,所以再加i保证不会小于应有的数,而减1则保证除以i之后不会比应有的数大1
            for(ll j=max(2LL,(a+i-1)/i)*i;j<b;j+=i){
                is_prime_large[j-a]=false;
            }
        }
    }
    ll k=0;
    for(ll i=0;i<b-a;i++){
        if(is_prime_large[i]){
            k++;
        }
    }
    return k;
}
int main(void){
    //int num=sieve(100);
    ll a=22801763489;
    ll b=22801787297;
    ll num=segment_sieve(a,b);
    cout << num << endl;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324818238&siteId=291194637