【SPOJ-PRIME1】Prime Generator【区间质数筛】

来源:互联网 发布:c语言排序算法最快 编辑:程序博客网 时间:2024/05/22 02:25

果然SPOJ第二题就很有趣。


因为n太大,线性筛和普通判断方法都不行。于是要用区间筛。


先预处理出sqrt(n)以内的所有质数(大概是31622),埃氏筛可以承受,我写了线性筛。

然后对于一段区间[m, n],我们枚举这些质数的倍数,然后除去区间内的这些倍数,剩下的就是质数了。


有一点就是,枚举质数时当然不能一倍两倍的枚举。

对于一个质数p,我们可以直接求出一个枚举的最大起点,这个起点满足k * p <= m(k是整数,且k最大)。

由Ruler Function,可以得出k = m / p * p。


还有就是要注意1的特判...


然后就完啦。


#include <cstdio>#include <cmath>using namespace std;const int maxn = 100005, maxsqrtn = 31625;int prime[maxsqrtn], cnt;bool isnotprime[maxsqrtn];inline int iread() {int f = 1, x = 0; char ch = getchar();for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';return f * x;}void getprime() {isnotprime[1] = 1;for(int i = 2; i < maxsqrtn; i++) {if(!isnotprime[i]) prime[++cnt] = i;for(int j = 1; j <= cnt && i * prime[j] < maxsqrtn; j++) {isnotprime[i * prime[j]] = 1;if(i % prime[j] == 0) break;}}}int n, m;bool vis[maxn];int main() {getprime();int T = iread();while(T--) {m = iread(); n = iread(); int len = n - m + 1;for(int i = 0; i < len; i++) vis[i] = 0;for(int i = 1; i <= cnt && prime[i] <= n; i++) {for(int j = m / prime[i] * prime[i]; j <= n; j += prime[i]) {if(j < m || j == prime[i]) continue;vis[j - m] = 1;}}if(m == 1) vis[0] = 1;for(int i = 0; i < len; i++) if(!vis[i]) printf("%d\n", i + m);printf("\n");}return 0;}


0 0