poj 2689 Prime Distance (double筛筛出大素数)

来源:互联网 发布:算法设计与分析王红梅 编辑:程序博客网 时间:2024/06/09 23:42

题意:给两个数L,U,1<=L< U<=2,147,483,647,求在L,U间的两相邻素数最小距离和最大距离。

          距离的定义就是俩数相减绝对值。

          The difference between L and U will not exceed 1,000,000.


解析:范围太大了,无法一次性筛出大素数,由题中L与U间范围为1000000找切入点,即筛出L与U间的素数,再O(n)扫一遍。

          先筛出小素数,然后用小素数为基,筛出大素数,筛法异曲同工。

          筛小素数时先假设所有数都为素数,接下来定下一个素数,此素数的倍数全不为素数。

          大素数大概为8000多个,渐进复杂度 x / lnx 可以计算出来。

          筛大素数时同理,先假设全为素数,接下来先由小素数的倍数扫一遍筛出不为素数的,再由余下为素数的扫一遍筛出不为素数的数。


代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = 4 * atan(1.0);const double ee = exp(1.0);LL lo, hi;const int maxs = 5e4 + 10;LL smallPrime[maxs];bool isSmallPrime[maxs];int nSmallPrime;void doSmallPrime(){    memset(isSmallPrime, true, sizeof(isSmallPrime));    nSmallPrime = 0;    for (LL i = 2; i < maxs; i++)    {        if (isSmallPrime[i])        {            smallPrime[++nSmallPrime] = i;            for (LL j = i * i; j < maxs; j += i)            {                isSmallPrime[j] = false;            }        }    }}const int maxb = 1e6 + 10;LL bigPrime[maxb];bool isBigPrime[maxb];int nBigPrime;void doBigPrime(){    memset(isBigPrime, true, sizeof(isBigPrime));    for (LL i = 1; i <= nSmallPrime; i++)    {        LL t = lo / smallPrime[i];        while (t * smallPrime[i] < lo || t <= 1)        {            t++;        }        for (LL j = t * smallPrime[i]; j <= hi; j += smallPrime[i])        {            if (lo <= j)            {                isBigPrime[j - lo] = false;            }        }    }    if (lo == 1)        isBigPrime[0] = false;    nBigPrime = 0;    for (LL i = 0; i <= hi - lo; i++)    {        if (isBigPrime[i])        {            bigPrime[++nBigPrime] = i + lo;        }    }}int main(){    #ifdef LOCAL    freopen("in.txt", "r", stdin);    #endif // LOCAL    doSmallPrime();    while (scanf("%lld%lld", &lo, &hi) == 2)    {        doBigPrime();        if (nBigPrime <= 1)            printf("There are no adjacent primes.\n");        else        {            LL minn = inf, maxx = 0;            LL minl = -1, minr = -1;            LL maxl = -1, maxr = -1;            for (int i = 1; i < nBigPrime; i++)            {                if (bigPrime[i + 1] - bigPrime[i] < minn)                {                    minn = bigPrime[i + 1] - bigPrime[i];                    minl = bigPrime[i], minr = bigPrime[i + 1];                }                if (maxx < bigPrime[i + 1] - bigPrime[i])                {                    maxx = bigPrime[i + 1] - bigPrime[i];                    maxl = bigPrime[i], maxr = bigPrime[i + 1];                }            }            printf("%lld,%lld are closest, %lld,%lld are most distant.\n", minl, minr, maxl, maxr);        }    }    return 0;}


0 0