【算法竞赛进阶指南】- 质数距离/prime distance - poj2689

题目描述 

给定两个整数L和U,你需要在闭区间[L,U]内找到距离最接近的两个相邻质数C1和C2(即C2-C1是最小的),如果存在相同距离的其他相邻质数对,则输出第一对。

同时,你还需要找到距离最远的两个相邻质数D1和D2(即D1-D2是最大的),如果存在相同距离的其他相邻质数对,则输出第一对。

输入格式

每行输入两个整数L和U,其中L和U的差值不会超过1000000。

输出格式

对于每个L和U ,输出一个结果,结果占一行。

结果包括距离最近的相邻质数对和距离最远的相邻质数对。(具体格式参照样例)

如果L和U之间不存在质数对,则输出“There are no adjacent primes.”。

数据范围

1\leq L\leq U\leq 2^{31} - 1

输入样例:

2 17
14 17

输出样例:

2,3 are closest, 7,11 are most distant.
There are no adjacent primes.
难度:中等
时/空限制:1s / 64MB
来源:《算法竞赛进阶指南》
算法标签

数学知识 质数

 

 

题目大意:

给定两个整数L,U(1\leq L\leq U\leq 2^{31} - 1,U-L\leq 10^{6}),求闭区间【L,U】中相邻两个质数的差最小和最大为多少。

题目分析:

L,U的范围很大,任何已知算法都无法在规定时间内生成[1, U]中所有质数,但是U - L的范围只有10的六次方,因此我们只需要用算法竞赛中常用的Eratosthenes筛法(埃拉托斯特尼筛法,简称埃氏筛法)求出2\sim \sqrt{U}之间所有质数,对于每个质数p,把【L,U】中能被p整除的数标记,即标记i*p为合数,其中i范围为\left \lceil {\frac{L}{p}}\right \rceil \leq i\leq \left \lfloor \frac{U}{p} \right \rfloor,最终遍历一遍【L,U】区间筛出来的质数求最大值,最小值即可。

该做法的时间复杂度为O \left ( \sqrt{U}loglog\sqrt{U} + \left ( U - L \right )loglogU \right )(书上写的)

一些细节要注意,不然很容易段错误,具体看代码注释

代码:

#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int N = 5e4 + 10;
const int M = 1e6 + 10;
int vt[M];
vector  prime, ans;
void init()
{
    memset(vt, 1, sizeof(vt));
    for (int i = 2; i <= N; ++ i){
        if (vt) prime.push_back(i);
        for (int j = 2; j <= N / i; ++ j) vt[i * j] = 0;
    }
}
int main()
{
    init();
    ll l, r;
    while (cin >> l >> r){
        ans.clear();
        memset(vt, 1, sizeof(vt));
        if (l == 1) vt[0] = 0;
        for (int i = 0; i < prime.size(); ++ i){//这里其实还可以优化,但没必要
            for (int j = (l - 1) / prime[i] + 1; j <= r / prime[i]; ++ j) if (j > 1) vt[prime[i] * j - l] = 0;//j 要大于1,取0会使下标为负导致段错误,取1会把素数也给标记掉
        }
        for (unsigned int i = l; i <= r; ++ i){//不能int,i = r = 2,147,483,647时,r再+1会溢出变为负,仍小于r,此时会导致死循环,vector所占空间太大导致段错误
            if (vt[i - l]) ans.push_back(i);
        }
        int minn = 0x7fffffff, maxx = 0;
        int pos1, pos2;
        for (int i = 0; i < ans.size() - 1; ++ i){
            int tmp = ans[i + 1] - ans[i];
            if (tmp > maxx){
                maxx = tmp;
                pos2 = i;
            }   
            if (tmp < minn){
                minn = tmp;
                pos1 = i;
            }
        }
        if (maxx == 0) cout << "There are no adjacent primes." << endl;
        else printf("%d,%d are closest, %d,%d are most distant.\n", ans[pos1], ans[pos1 + 1], ans[pos2], ans[pos2 + 1]);
    }
    return 0;
}

 

你可能感兴趣的:(【算法竞赛进阶指南】- 质数距离/prime distance - poj2689)