素数筛(1) 埃氏筛法
其原理就是先将2-n之内的所有数存在一个数组里,初始化所有数全为素数,然后从2开始寻找,只要标记是素数便将他的所有倍数的标记都改为合数,依次类推。时间复杂度为O(nloglogn)。
代码实现
1 void prime_table() 2 { 3 for(int i=2;(LL)i<=n;i++) prime[i]=1; 4 for(int i=2;(LL)i*i<=n;i++) 5 if(prime[i]) for(LL j=i*i;j<=n;j+=i) prime[j]=0; 6 }
区间素数筛
当要求的范围过大时,上述方法会爆内存,所以我们可以先做好【2,√b)和【a,b)的表,在筛【2,√b)的同时将其倍数在【a,b)中划去。
40027120区间内素数的个数 |
难度级别:B; 运行时间限制:1000ms; 运行空间限制:262144KB; 代码长度限制:2000000B |
试题描述
|
给定两个正整数 a 和 b,请你统计区间 [a,b) 内有多少个素数。 |
输入
|
共一行包含两个正整数 a 和 b,用一个空格分隔开。
|
输出
|
一个数,表示所给区间内的素数的个数。
|
输入示例
|
22 37
|
输出示例
|
3
|
其他说明
|
数据范围:1≤ a < b ≤ 10^12 , b-a ≤ 10^7 。
样例说明:有23、 29 和 31 共 3 个素数。 |
1 #include<iostream> 2 using namespace std; 3 #define LL long long 4 LL read() 5 { 6 LL x=0,f=1; 7 char c=getchar(); 8 while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); } 9 while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); } 10 return x*f; 11 } 12 #define maxn 1000010 13 bool prime[maxn], is[maxn]; 14 LL a, b; 15 void prime_table() 16 { 17 for(int i = 2; (LL)i * i < b; i++) prime[i] = 1; 18 for(int i = 0; i < b - a; i++) is[i] = 1; 19 for(int i = 2; (LL)i * i < b; i++) if(prime[i]) { 20 for(LL j = 2 * i; j * j < b; j += i) prime[j] = 0; 21 for(LL j = max(2LL, (a + i - 1) / i) * i; j <= b; j += i) if(j >= a) is[j-a] = 0; 22 } 23 return ; 24 } 25 26 int main() 27 { 28 a = read(); b = read(); 29 prime_table(); 30 int cnt = 0; 31 for(int i = 0; i < b - a; i++) if(is[i]) cnt++; 32 if(a == 1) cnt--; 33 printf("%d\n", cnt); 34 35 return 0; 36 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~