素数打表的方法是数论里面非常常用的技巧,如果数比较大的话,筛出其中的素数跟普通筛的原理差不多。
就是给数组一个偏移量,然后来筛取,比如用0~100000来表示100000000~100100000的素数表,弄一个100000000的偏移量就好了
每次,写随笔之前基本上都自己敲一遍代码,然后提交看看,果然写出来的还是有那么点问题,还要调试调试。之前AC的代码,是骗自己的代码。
自欺欺人实例,把prime和prime2分开来考虑,当L大一点时候用prime2,否则用普通素数表。其实是有BUG的。。。就是自己设置的L大一点是大多少,如果太大就会正好卡掉几个普通素数表的没有存储的素数,当时AC了,就没仔细思考,现在回头想明白了。
正确代码:
#include <stdio.h> #include <iostream> #include <string.h> using namespace std; const int N = 1e6 + 50; typedef long long LL; int vis[N]; int prime[N]; int cnt = 0; int cnt2 = 0; int prime2[N]; void getPrime() { cnt = 0; memset(vis, 0, sizeof(vis)); for(int i = 2; i < N; i++) { if(!vis[i]) { prime[cnt++] = i; for(int j = i*2; j < N; j+= i) vis[i] = 1; } } } void getPrime2(LL L, LL R) { cnt2 = 0; if(L < 2) L = 2; memset(vis, 0, sizeof(vis)); for(LL i = 0; (LL)prime[i]*prime[i] <= R; i++) { LL k = L / prime[i] + (L % prime[i] > 0); //想上取整 if(k == 1) k = 2; for(LL j = k*prime[i]; j <= R; j += prime[i]) { vis[j - L] = 1; } } for(LL i = L; i <= R; i++) { if(!vis[i - L]) { prime2[cnt2++] = i; } } } int main() { getPrime(); int l, r; while(scanf("%d%d", &l, &r) == 2) { getPrime2((LL)l, (LL)r); int x1, y1, x2, y2; if(cnt2 <= 1) { printf("There are no adjacent primes. "); continue; } x1 = x2 = prime2[0]; y1 = y2 = prime2[1]; for(int i = 1; i < cnt2; i++) { if(prime2[i] - prime2[i-1] < y1-x1) { x1 = prime2[i-1]; y1 = prime2[i]; } if(prime2[i] - prime2[i-1] > y2-x2) { x2 = prime2[i-1]; y2 = prime2[i]; } } printf("%d,%d are closest, %d,%d are most distant. ",x1,y1,x2,y2); } return 0; }