ACM模板——素数相关

//整数分解 如400: 2 4 \n 5 2 
map<int,int> prime_factor(int n)
{
    map<int,int> res;
    for(int i = 2;i * i <= n;i ++)
        while(n % i==0)
        {
            ++res[i];
            n/=i;
        }
    
    if(n!=1) res[n] = 1;
    return res;
}
整数分解
//约数枚举 列举出所有的约数 
vector<int> divisor(int n)
{
    vector<int> res;
    for(int i = 1;i * i <= n;i ++)
        if(n%i==0)
        {
            res.pb(i);
            if(i!=n/i) res.pb(n/i);
        }
    return res;
}
约数枚举
//判断是否为合数 
bool is_prime(int n)
{
    for(int i = 2;i * i <= n;i ++)
        if(n%i==0) return false;
    return n != 1;
}
判断素数
//对区间[a,b)内的整数执行筛法,is_prime[i-a]=true  ---  表示i是素数 注意这里下标偏移了a,所以从0开始。
const int maxL = 200000;
const int maxBMA = 50003;
bool is_prime[maxL];//对0-maxn的数字进行素数筛 ,maxL要大于根号b 
bool is_prime_small[maxBMA];//b-a的最大可能值 ,maxBMA要大于b-a 
ll prime[maxn];//存a到b的素数表 
ll segment_sieve(ll a,ll b)
{
    for(ll i=0; (ll)i*i<b; ++i) is_prime_small[i]=true; //对[2,sqrt(b))的初始化全为质数
    for(ll i=0; i<b-a; i ++) is_prime[i]=true; //对下标偏移后的[a,b)进行初始化

    for(ll i=2; (ll)i*i<b; i ++)
    {
        if(is_prime_small[i])
        {
            for(ll j=2*i; (ll)j*j<b; j+=i) is_prime_small[j]=false; //筛选[2,sqrt(b));
            //(a+i-1)/i*i得到最接近a的i的倍数,最低是i的2倍,然后筛选
            for(ll j=max(2LL,(a+i-1)/i)*i; j<b; j+=i) is_prime[j-a]=false;
        }
    }
    ll res = 0;
    for(ll i=0; i<b-a; ++i) //统计个数
        if(is_prime[i]) prime[res++]=i+a;
    return res;
}
大区间素数
const int maxn = 50003;
int prime[maxn],vis[maxn];
int db(int n)
{
    int i,j;
    int k=0;
    for(i=2; i<=n; i++)
    {
        if(!vis[i])    prime[k++]=i;
        for(j=0; j<k; j++)
        {
            if(prime[j]*i>n)    break;
            vis[prime[j]*i]=1;
            if(i%prime[j]==0)    break;
        }
    }
    return k;
}
欧拉筛打素数表
const int maxn = 50003;
int prime[maxn],vis[maxn];
int db(int n)
{
    int p = 0;
    for(int i = 0;i <= n;i ++) vis[i] = true;
    vis[0] = vis[1] = false;
    for(int i = 2;i <= n;i ++)
        if(vis[i])
        {
            prime[p++] = i;
            for(int j = 2 * i;j <= n;j += i) vis[j] = false;
        }
    return p;
}
埃氏筛打素数表

 db函数里加一个vis[1] = 1; 当!vis[num]成立时,num为素数

posted @ 2019-03-27 20:13  Asurudo  阅读(258)  评论(0)    收藏  举报