LightOJ 1197 LightOJ 1197(大区间素数筛选)
http://lightoj.com/volume_showproblem.php?problem=1197
题目大意:
就是给你一个区间[a,b]让你求这个区间素数的个数
但a、b的值太大没法直接进行素数筛选(没法开那么大的数组),我们可以将a当做0,将b当做b-a
这样求[a,b]之间就变成了求[0, b - a]之间,这样就可以开数组来筛选
下图是代码式子j = j + prime[i] - a % prime[i]的由来
#include<stdio.h> #include<math.h> #include<string.h> #include<stdlib.h> #include<algorithm> using namespace std; const int N = 1e5 + 10; const int INF = 0x3f3f3f3f; typedef long long ll; int prime[N], f[N], k; bool Isprime[N]; void Prime() { k = 0; memset(Isprime, true, sizeof(Isprime)); Isprime[1] = false; for(int i = 2 ; i < N ; i++) { if(Isprime[i]) { prime[k++] = i; for(int j = 2 ; i * j < N ; j++) Isprime[i * j] = false; } } }//先用素数筛选法筛选出小范围的素数 int main() { int t, a, b, p = 0; scanf("%d", &t); Prime(); while(t--) { p++; memset(f, 0, sizeof(f)); int num = 0; scanf("%d%d", &a, &b); int l = b - a;//将a到b转化为从0到b - a for(int i = 0 ; i < k && prime[i] * prime[i] <= b ; i++) { int j = 0; if(a % prime[i] != 0)//判断a + j 如果(a + j)% prime[i] != 0,则将a + j筛除 j = j + prime[i] - a % prime[i]; if(a + j == prime[i])//如果a + j是素数,则找下一个 j += prime[i]; for(; j <= l ; j += prime[i]) f[j] = 1;//从j开始将含prime[i]因子的数标记(即筛除) } for(int i = 0 ; i <= l ; i++) if(!f[i]) num++; if(a == 1)//如果a从1开始,需要减去一个 num--; printf("Case %d: %d\n", p, num); } return 0; }