DES:给出一个区间[L, U]。找出这个区间内相邻的距离最近的两个素数和距离最远的两个素数。其中1<=L<U<=2147483647 区间长度不超过1000000.
思路:因为给出的U的范围超出了int的最大。所以不能直接打出1-U的素数表。【我们知道。利用素数筛法时是把所有的合数都筛掉了。那么我们也想办法把L-U内的合数都筛掉就可以了。那么只要用sqrt(U)内的素数去筛掉L-U的合数就可以了。】只是大概理解。。。。。。。
1 #include <stdio.h> 2 #include <iostream> 3 #include <string.h> 4 #include <iostream> 5 using namespace std; 6 7 #define N 500000 8 #define len 10000000 9 #define inf 0x7fffffff 10 bool isprime[N+5]; 11 long long prime[N], cnt; 12 bool res[len+5]; 13 14 void init() { // 筛选50000内的素数。要注意i比较大时 会容易超int的范围 15 long long i, j; 16 cnt = 0; 17 memset(isprime, true, sizeof(isprime)); 18 for (i=2; i<=N; ++i) { 19 if (isprime[i]) { 20 prime[cnt++] = i; 21 if (i*i <= N) { 22 for (j=i*i; j<=N; j+=i) { 23 isprime[j] = false; 24 } 25 } 26 } 27 } 28 } 29 30 int main() { 31 long long L, U, i, j, k, minn, maxx, s, t; 32 init(); 33 while(~scanf("%lld%lld", &L, &U)) { 34 memset(res, 0, sizeof(res)); 35 for (i=0; i<cnt; ++i) { 36 s = (L-1)/prime[i]+1; // s和t表示了当前范围里的数对这个素数的最小倍数和最大倍数。 比如说 区间[3, 9] 对素数2 的 s 和 t 应是 2, 4 37 t = U/prime[i]; // 由这个例子可以知道为什么 L-1 最后再+1。t就可以直接除。 38 for (j=s; j<=t; ++j) { // 筛选出区间内的素数 39 if (j>1) { // 不知道为什么==1的时候也不算????? 40 res[j*prime[i]-L] = true; 41 } 42 } 43 } 44 k = -1, minn = inf, maxx = -1; 45 long long dis, m1, m2; 46 for (i=0; i<=U-L; ++i) { // 求解最优值 47 if (!res[i]) { 48 if (k!=-1) { 49 dis=i-k; // 记录两个素数的最远距离。 50 if (dis > maxx) { 51 maxx = dis; 52 m1 = i; 53 } 54 if (dis < minn) { 55 minn = dis; 56 m2 = i; 57 } 58 } 59 if (i+L != 1) // 注意1 的时候特殊判断1不是素数。 60 k=i; 61 } 62 } 63 if (maxx == -1) 64 printf("There are no adjacent primes.\n"); 65 else printf("%lld,%lld are closest, %lld,%lld are most distant.\n", m2-minn+L, m2+L, m1-maxx+L, m1+L); 66 } 67 return 0; 68 }
代码可以理解。裸敲好像。。。还是有一点难度。明天再敲一遍。