POJ-2689 Prime Distance 区间筛法

区间筛法:L~R,先筛出根号R的素数,再用这些素数把L ~ R的合数筛掉,剩下就是素数,适合R大,区间小的素数区间。

题目链接: http://poj.org/problem?id=2689

题意: 给出一个区间 [l, r] 求其中相邻的距离最近和最远的素数对 . 其中 1 <= l < r <= 2,147,483,647, r - l <= 1e6 .

思路: 素数区间筛

要找到 [l, r] 中相邻最近和最远的素数对肯定是需要找出 [l, r] 内所有素数 . 但是无论是直接线性打表还是暴力都处理不了这么大的数据 .

可以先给 sqrt (r ) 内的素数打个表, 再用 sqrt(r ) 内的素数去筛选 [l, r] 内的合数, 然后再遍历一次 [l, r], 记录答案即可 。

#include
#include
#include
#include
using namespace std;
int cnt,L,R,X1,Y1,X2,Y2;
const int maxn=1000001;
bool is_prime[maxn];
bool flag[maxn];
int a[maxn];
int b[maxn];
void Prime()
{
    /*int n=46340;
    cnt=0;
    is_prime[1]=0;
    for(int i=2;i<=n;i++)
        is_prime[i]=1;
    for(int i=2;i*i<=n;i++)
    {
        if(is_prime[i])
        {
            a[++cnt]=i;
            for(int j=i*i;j<=n;j+=i)
            {
                is_prime[j]=0;
            }
        }

    }
    */

	memset(is_prime, 1, sizeof(is_prime));
	for (int i = 2; i <= 46340; i++)
		if (is_prime[i])
		{
			a[++cnt] = i;
			for (int j = 2; j <= 46340 / i; j++) is_prime[i*j] = false;
		}
}
int main ()
{
    Prime();
    while(scanf("%d%d",&L,&R)!=EOF)
    {

       int cnt2=0;
       //cout << cnt2;
        memset(flag, 1, sizeof(flag));
        for(int i=1;i<=cnt;i++)
        {
            for(int j=L/a[i];j<=R/a[i];j++)
            {
                if(j>1){
                    //cout << j <
                flag[j*a[i]-L]=0;
                //cout << j*a[i]-L<
                }
            }
        }
    if(L==1) flag[0]=0;
        for(int j=0;j<=R-L;j++)
        {
            if(flag[j]==1)
            {
                b[++cnt2]=L+j;
                //if (i == R) break;
                //cout <
            }
        }
        int minx=2147483647,maxx=-1;
        for(int i=1;i<cnt2;i++)
        {
            int t=b[i+1]-b[i];
            if(t>maxx)
            {
                maxx=t;
                Y1=b[i];
                Y2=b[i+1];
            }
            if(t<minx)
            {
                minx=t;
                X1=b[i];
                X2=b[i+1];
            }
        }
       //cout << cnt2 <
        if(cnt2<2)
            printf("There are no adjacent primes.\n");
        else
            printf("%d,%d are closest, %d,%d are most distant.\n",X1,X2,Y1,Y2);

    }



   return 0;
}

坑点:
1.bool定义flag数组,不然容易memset成1出错。
2.int正好是2,147,483,647,for循环到这个数要直接跳出,不能返回循环体+1会溢出int。
或者直接枚举偏移量。

你可能感兴趣的:(算法竞赛)