这道题是学习素数筛法的经典,应用到了区间筛素数。具体思路是先筛出1到sqrt(2147483647)之间的所有素数,然后再通过已经晒好素数筛出给定区间的素数,关于筛素数的问题,我转载了一篇网上一个人总结的素数总结,里面就有关于筛大数区间的素数的算法。虽然说一切都已经具备了,但是这道题我第一次做的时候RUNTIME ERROR了,原因是声明变量的时候用了long,当数据比较大的时候会超,第二次我改成long long,这才A掉。。总之,还有很多要学的东西,继续努力吧!!
#include<iostream> #include <cstdio> using namespace std; /** * prime[]:存储小范围的素数表 * prime1[]:存储某一区间的素数表 * pcount:小范围素数表中素数的个数 * pcount1:某一区间的素数表中素数的个数 * in[]、in1[]用来标记某一个数字是否为素数.. */ long long prime[46500], prime1[1000010]; long long pcount, p1count; long long in[46500], in1[1000010]; void getsprime() {//快速筛小范围素数 for (int i = 2; i < 46500; ++i){ in[i] = 1; } for (int i = 2; i < 46500; ++i) { if (!in[i]){ continue; } for (int j = i * 2; j < 46500; j += i){ in[j] = 0; } } pcount = 0; for (int i = 2; i < 46500; ++i){ if (in[i]){ prime[pcount++] = i; } } } void getlprime(long L, long U) { if (U < 46500) { //假如区间的最大值就小于46500的话,那么之际用我们刚才求完的就好了 p1count = 0; for (int i = L; i <= U; ++i){ if (in[i]){ prime1[p1count++] = i; } } } else { //筛大数区间内的素数的核心部分 long long k, size = U - L; for (long i = 0; i <= size; ++i){ in1[i] = 1; } for (long i = 0; i <= pcount && prime[i] * prime[i] <= U; ++i) { k = L / prime[i]; if (k * prime[i] < L){ ++k; } if (k <= 1){ ++k; } while (k * prime[i] <= U) { in1[k * prime[i] - L] = 0; ++k; } } p1count = 0; for (long i = 0; i <= size; ++i){ if (in1[i]){ prime1[p1count++] = i + L; } } } } int main() { getsprime(); long long L, U; while (scanf("%lld%lld", &L, &U) != EOF) { getlprime(L, U); long long distance, xmin, ymin, xmax, ymax; // long long min=2147483647,max=-1; int max = INT_MIN; int min = INT_MAX; if (p1count < 2) { printf("There are no adjacent primes.\n"); } else { long i; for (i = 0; i < p1count - 1; ++i) { distance = prime1[i + 1] - prime1[i]; if (distance < min) { min = distance; xmin = i; ymin = i + 1; } if (distance > max) { max = distance; xmax = i; ymax = i + 1; } } printf("%lld,%lld are closest, %lld,%lld are most distant.\n", prime1[xmin], prime1[ymin], prime1[xmax], prime1[ymax]); } } return 0; }