数学板块学习之素数

素数

线性素数筛:O(nlogn)

bool check[100005];
int prime[100005];     //储存第i个素数
void getprime(int n)
{
    memset(check, 0, sizeof(check));  // 标记数组初始化,初始均为 0
    int tot = 0;  // tot 初始为 0,用来记录质数总个数
    for (int i = 2; i <= n; ++i) {  // 从 2 开始枚举
        if (!check[i]) {  // 如果 i 没有被划去,则 i 为质数,加入质数表中
            prime[++tot] = i;
        }
        for (int j = 1; j <= tot; ++j) {  // 划去 i 与所有已筛出的质数的乘积
            if (i * prime[j] > n) {  // 判断合数是否在区间内
                break;
            }
            check[i * prime[j]] = 1;  // 划去在区间内的合数
            if (i % prime[j] == 0) {  // 保证合数只被其最小的质因子划去,提高筛选效率
                break;
            }
        }
    }

埃氏素数筛:O(nloglogn)

vector<int>prime;        //其中存储2-n的所有素数
bool is_prime[MAXN]   //存储第i项是否为素数 
void find_prime(int n)
{
    int p=0;
    for(int i=2;i<=n;i++)
        is_prime[i]=true;
    is_prime[0]=is_prime[1]=false;
    for(int i=2;i<=n;i++)
    {
        if(is_prime[i])
        {
            prime.push_back(i);
            for(int j=2*i;j<=n;j+=i)
                is_prime[j]=false;
        }
    }
}

区间素数模板

const int maxn=1e6;
ll prime[maxn+10];
ll prime2[maxn+10];
bool notprime[maxn+10];///某个数是否为素数,false是素数,ture不是
bool bignotprime[maxn+10];///大数区间的
bool prime(ll x)
{
    if(x==0||x==1||x==2) return false;
    for(int i=2;i*i<=x;i++)
        if(x%i==0) return false;
    return true;
}
void getnotprime()///某个数是否为素数
{
    memset(notprime,false,sizeof(notprime));
    notprime[0]=notprime[1]=true;
    for(int i=2;i<maxn;i++)
    if(!notprime[i])///不是素数
    {
        if(i>maxn/i) continue;
        for(int j=2*i;j<maxn;j+=i)///往上更新
            notprime[j]=true;
    }
}
void getprime()/// O(n)素数筛,把素数筛出来
{
    memset(prime,0,sizeof(prime));
    for(int i=2;i<=maxn;i++)
    {
        if(!prime[i]) prime[++prime[0]]=i;
        for(int j=1;j<=prime[0]&&prime[j]<=maxn/i;j++)
        {
            prime[prime[j]*i]=1;
            if(i%prime[j]==0) break;
        }
    }
}
void getprime2(ll L,ll R)///L,R为大数,区间范围1e6以内.
{
    memset(bignotprime,false,sizeof(bignotprime));
    if(L < 2)	L = 2;
    for(ll i=1;i<=prime[0]&&(long long)prime[i]*prime[i]<=R;i++)
    {
        ll pp=L/prime[i]+(L%prime[i]>0);
        if(pp==1)pp=2;
        for(ll j=pp;(long long)j*prime[i]<=R;j++)
        if((long long)j*prime[i]>=L)
        bignotprime[j*prime[i]-L]=true; ///将大数映射到小数来记录,因为开不到那么大的数组
    }
        prime2[0]=0;
        for(ll i=0;i<=R-L;i++)
        if(!bignotprime[i])
        prime2[++prime2[0]]=i+L;
}
int main()
{
    ll a,b;
    prime(x);///判断某个数是否为素数
    getprime();///prime[]
    getnotprime();/// notprime[]
    getprime2(a,b);///得到prime2[]和bignotprime[],其中判断某个大数x是否为素数,bignotprime[x-a]:true表示不是,false表示是.
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值