题目链接:http://lightoj.com/volume_showproblem.php?problem=1197
题意:给你两个数 a b,求区间 [a, b]内素数的个数, a and b (1 ≤ a ≤ b < 231, b - a ≤ 100000).
由于a和b较大,我们可以筛选所有[2, √b)内的素数,然后同时去筛选掉在区间[a, b)的数,用IsPrime[i-a] = 1表示i是素数;
///LightOj1197求区间素数的个数; #include<stdio.h> #include<string.h> #include<iostream> #include<vector> using namespace std; typedef long long LL; const int oo = 0xfffffff; const int N = 1e6+5; int IsPrime[N]; ///IsPrime[i-a] = 1说明i是素数; int Prime[N]; ///Prime[i] = 1说明i是素数,i比较小; ///对区间[a, b)内的素数进行筛选; void Segment_sieve(LL a, LL b) { for(int i=0; (LL)i*i<b; i++) Prime[i] = 1; for(int i=0; i<b-a; i++) IsPrime[i] = 1; for(int i=2; (LL)i*i<b; i++) { if(Prime[i]) { for(int j=i+i; (LL)j*j<b; j+=i)///筛选2---sqrt(b)的素数; Prime[j] = 0; for(LL j=i*max(2LL, (a+i-1)/i); j<b; j+=i)///筛选出[a, b)上是i的倍数的那些数; IsPrime[j-a] = 0; } } } int main() { int T, t = 1; scanf("%d", &T); while(T--) { LL a, b; scanf("%lld %lld", &a, &b); Segment_sieve(a, b+1); int ans = 0; for(int i=0; i<=b-a; i++) if(IsPrime[i])ans ++; if(a <= 1)///1不是素数,所以要单独处理; ans --; printf("Case %d: %d ", t++, ans); } return 0; }