区间筛法 (埃氏筛变种)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34271269/article/details/52734318

最近看到白书上的区间筛法 就根据区间筛自己打了一段代码 理解了一下里面的原理

这个题目我最初一眼看过去就是一次筛法 但是根本不可行啊 时间空间肯定会爆炸 书上介绍说可以用小于等于根下b的素数来筛 刚开始我觉得会超时

但是后来分析了一下这个算法其实还是蛮高效的

1.首先我们要明白一点 : a-b这个区间里边的数之可能被小于等于根下b的素数筛掉 

那么我们可以一边找根下b的素数 一边把他们的倍数从a-b里面删除

2.那么我们最坏情况下要执行根下b-2的次数的大循环 每次小循环 我们估计实现的次数为 (b-a)/i 那么从 2 - max(素数) 累加求和 那么最后会得到一个小于欧拉常数*(b-a)的值 我们就可以知道这个算法是可行的!

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int maxn =1e6+5;
bool isprime[maxn];
bool lowisprime[maxn];
void segment_sieve(long long a,long long b)
{
    for(int i=0;i<1e6+5;i++) isprime[i]=lowisprime[i]=true;
    for(int i=2;(long long )i*i<b;i++)
    {
        if(lowisprime[i])
        {
            for(int j=2*i;(long long)j*j<b;j+=i) lowisprime[j]=false;
            for(long long j=(a/i)*i;j<b;j+=i) if(j>=a&&j<b) isprime[j-a]=false;
        }
    }
}
int main()
{
    long long a,b;
    cin>>a>>b;
    cout<<endl;
    segment_sieve(a,b);
    int cnt=0;
    for(int i=0;i<b-a;i++) if(isprime[i]) cnt++;
    cout<<cnt<<endl;
    return 0;
}



猜你喜欢

转载自blog.csdn.net/qq_34271269/article/details/52734318