zoukankan      html  css  js  c++  java
  • [题解] POJ2689 [质数距离]

    质数距离

    题目TP门

    题目描述

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

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

    输入格式

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

    输出格式

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

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

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

    样例

    样例输入

    2 17
    14 17
    

    样例输出

    2,3 are closest, 7,11 are most distant.
    There are no adjacent primes.
    
    数据范围

    1≤L<R≤2147483647

    解析

    L,R范围很大,即使是线性筛法也无法在有限时间内筛选出质数。
    我们知道,在任何一个合数n中,必有一个小于sqrt(n)的因子。
    所以先用任意筛法(时间复杂度<=O(n))筛出所有在sqrt( R )中的质数。
    把这些数记为p。


    不难想到,在[L,R]中的数,只要不被p整除,就是质数。找出[L,R]中的质数之后,后面的操作就很简单了。
    于是我就想到了枚举L~R中所有的数,能否被P整除

    代码如下
    #include <cstdio>
    #include <cmath>
    #include <vector>
    #include <cstring>
    using namespace std;
    #define ll long long
    const ll MAXN = 1e7 + 5;
    vector<ll> zs;
    bool f[MAXN];
    ll ans1, ans2, ans3, ans4, maxn, minn;
    ll l, r, size;
    void Sqrt_R() {
        ll i, j;
        f[1] = 1;
        size = 0;
        zs.clear();
        for (i = 2; i <= sqrt(r); i++) {
            if (f[i])
                continue;
            zs.push_back(i);
            for (j = 1; j <= sqrt(r) / i; j++) f[i * j] = 1;
        }
    }
    void Prime_Number() {
        ll i, j;
        ll last, l1, cnt = 0;
        minn = 0x3f3f3f3f;
        maxn = -minn;
        for (i = l; i <= r; i++) {
            bool flag = 0;
            for (vector<ll>::iterator it = zs.begin(); it != zs.end(); it++) {
                if (i % (*it) == 0) {
                    flag = 1;
                    break;
                }
            }
            if (i >= 2 && i <= sqrt(r))
                if (flag && (!f[i]))
                    continue;
            if (flag && (!(i >= 2 && i <= sqrt(r))))
                continue;
            cnt++;
            if (cnt >= 2) {
                ll min1 = i - last;
                if (min1 < minn) {
                    ans1 = l1;
                    ans2 = i;
                    minn = min1;
                }
                ll max1 = i - last;
                if (max1 > maxn) {
                    ans3 = l1;
                    ans4 = i;
                    maxn = max1;
                }
            }
            last = i;
            l1 = i;
        }
        if (cnt >= 2)
            printf("%lld,%lld are closest, %lld,%lld are most distant.
    ", ans1, ans2, ans3, ans4);
        else
            printf("There are no adjacent primes.
    ");
    }
    int main() {
        while (scanf("%lld %lld", &l, &r) != EOF) {
            memset(f, 0, sizeof(f));
            Sqrt_R();
            Prime_Number();
        }
        return 0;
    }
    

    这种的时间复杂度是O((L-R)*sqrt( R)),于是,我超时了。
    在这里插入图片描述
    于是在上述方法的改进下,在找p的时候,把[L,R]中能整除p的数标记了,时间复杂度就可以减少到O(L-R),就不会超时。

    正解
    #include <cstdio>
    #include <cmath>
    #include <vector>
    #include <cstring>
    using namespace std;
    #define ll long long
    const ll MAXN = 1e7 + 5;
    bool f[MAXN], p[MAXN];
    ll ans1, ans2, ans3, ans4, maxn, minn;
    ll l, r;
    void Sqrt_R() {
        ll i, j;
        f[1] = 1;
        for (i = 2; i <= sqrt(r); i++) {
            if (f[i])
                continue;
            ll u = (l - 1) / i + 1;
            while ((u * i) < l) u++;
            if (u < 2)
                u = 2;
            while ((u * i) <= r) {
                p[(u * i) - l] = 1;
                u++;
            }
        }
    }
    void Prime_Number() {
        ll i, j;
        ll last, l1, cnt = 0;
        minn = 0x7fffffff;
        maxn = -minn;
        for (i = l; i <= r; i++) {
            if (!p[i - l] && i != 1) {
                if (i - last < minn && cnt != 0) {
                    minn = i - last;
                    ans1 = last;
                    ans2 = i;
                }
                if (i - last > maxn && cnt != 0) {
                    maxn = i - last;
                    ans3 = last;
                    ans4 = i;
                }
                last = i;
                cnt++;
            }
        }
        if (cnt >= 2)
            printf("%lld,%lld are closest, %lld,%lld are most distant.
    ", ans1, ans2, ans3, ans4);
        else
            printf("There are no adjacent primes.
    ");
    }
    int main() {
        while (scanf("%lld %lld", &l, &r) != EOF) {
            memset(f, 0, sizeof(f));
            memset(p, 0, sizeof(p));
            Sqrt_R();
            Prime_Number();
        }
        return 0;
    }
    

    这道题用了埃氏筛法的思想。
    单独来看,筛选1-n中的质数,时间复杂度只有O(n*log(n)),是竞赛中最常用的质数筛法。
    在这里插入图片描述

  • 相关阅读:
    mvc session验证
    mvc登录验证
    PHP中return的用法
    mvc框架类
    php mvc实现比赛列表
    php MySQLDB类
    php header的几种用法
    php isset()与empty()的使用
    jenkins+springboot+svn linux 自动化部署
    基于netty的websocket例子
  • 原文地址:https://www.cnblogs.com/C202202chenkelin/p/13904355.html
Copyright © 2011-2022 走看看