zoukankan      html  css  js  c++  java
  • 区间素数筛法

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

    a<b<=10^12

    b-a<=10^6

    因为b以内合数的最小质因数一定不超过sqrt(b),如果有sqrt(b)以内的素数表的话,就可以把筛选法用在[a,b)上了,先分别做好[2,sqrt(b))的表和[a,b)的表,然后从[2,sqrt(b))的表中筛得素数的同时,也将其倍数从[a,b)的表中划去,最后剩下的就是区间[a,b)内的素数了。

    有的时候需要求出某个特定区间的素数,但是数可能很大,数组也开不小,所以需要进行下标偏移,这样才可以使用筛选法。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 typedef long long ll;
     6 const int maxn = 1000005;
     7 bool is_prime[maxn];
     8 bool is_prime_small[maxn];
     9 ll prime[maxn];
    10 ll prime_num=0;
    11 
    12 //对区间[a,b)内的整数执行筛法,is_prime[i-a]=true  ---  表示i是素数 注意这里下标偏移了a,所以从0开始。
    13 void segment_sieve(ll a,ll b) {
    14     for(ll i=0;i*i<b;++i) is_prime_small[i]=true; //对[2,sqrt(b))的初始化全为质数
    15     for(ll i=0;i<b-a;++i) is_prime[i]=true; //对下标偏移后的[a,b)进行初始化
    16 
    17     for(ll i=2;i*i<b;++i) {
    18         if(is_prime_small[i]) {
    19             for(ll j=2*i;j*j<b;j+=i) is_prime_small[j]=false;  //筛选[2,sqrt(b));
    20             //(a+i-1)/i得到最接近a的i的倍数,最低是i的2倍,然后筛选
    21             for(ll j=max(2LL,(a+i-1)/i)*i;j<b;j+=i) is_prime[j-a]=false;
    22         }
    23     }
    24     for(ll i=0;i<b-a;++i)  //统计个数
    25         if(is_prime[i]) prime[prime_num++]=i+a;
    26 }
    27 
    28 int main()
    29 {
    30     ll a,b;
    31     while(~scanf("%lld%lld",&a,&b))
    32     {
    33         prime_num=0;
    34         memset(prime,0,sizeof(prime));
    35         segment_sieve(a,b);
    36         //for(ll i=0;i<prime_num;++i) printf("%lld
    ",prime[i]);
    37         printf("%lld
    ",prime_num);
    38     }
    39     return 0;
    40 }
  • 相关阅读:
    Springboot中使用Scala开发
    aliyun阿里云Maven仓库地址
    css文字滚动
    随笔
    下拉菜单事件
    微信分享
    微信分享功能
    随笔记
    全屏设置
    判定复选框的选中状态
  • 原文地址:https://www.cnblogs.com/nowandforever/p/4515612.html
Copyright © 2011-2022 走看看