POJ2689 Eratothenes质数筛

POJ2689 Eratothenes质数筛

Waterloo October 1998
https://vjudge.net/problem/POJ-2689

通过某种方式到waterloo的官网(http://acm.student.cs.uwaterloo.ca/~acm00/98oct17/solutions/)上找到了测试数据:

//data.in

1 100
1000000000 1001000000
1000000000 1000000008
2147483587 2147483647
2147481000 2147483646
1 2
2 3

//data.out

2,3 are closest, 89,97 are most distant.
1000000007,1000000009 are closest, 1000097621,1000097797 are most distant.
There are no adjacent primes.
2147483629,2147483647 are closest, 2147483587,2147483629 are most distant.
2147481899,2147481901 are closest, 2147481673,2147481793 are most distant.
There are no adjacent primes.
2,3 are closest, 2,3 are most distant.

题目大意
给出左右边界l,r(1<=l<r<=2<<31),r-l<=1e6,问其中相邻的质数最近的是哪两个,最远的是哪两个
,如果期间没有相邻质数就输出没有

解法
2<<31是肯定不可能直接筛的,但是因为任意i>=2的合数都存在j<=sqrt(i),使得j整除i,那就用Eratothenes筛一下sqrt(2<<31)(46000多,所以开了47000)以下的质数i,然后在从ceiling(l/i)到floor(r/i)依次乘因子i(又有点像Eratothenes)从而标记l,r之间的合数,从而筛出质数,然后遍历即可

注意事项
1)数组要开大一点(1e6+1000),否则会RE,多开个一千分之一没什么大不了的
2)注意1不是质数,所以需要特判,直接改成从2开始判(这思路真的想不到)

复习反省
1)忘了质数的倍数>=2的时候才能筛掉
2)忘了1特判(真香!)
3)不知道为什么eratothenes第一次写成了筛到 n \sqrt{n} n 就停了

AC代码
Time 125ms Memory 4604 KB length 1920 Lang G++
注意这里的used两次筛素数都用了

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;


const int maxn = 1e6+1000;
const int maxm = 47000;
int used[maxn];
int prime[maxm];
int num = 0;
void eratothses()
{
    memset(used,0,sizeof(used));
    for(int i = 2; i <=maxm; i++)
    {
        if(used[i])
        {
            continue;
        }
        else
        {
            prime[num++] = i;
            for(int j = 2; j<maxn/i; j++)
                used[i*j] = 1;
        }
    }
}
int main()
{
    int l,r;
    eratothses();
    while(cin >> l >> r)
    {
        for(int i = 0;i <r-l+1;i++)used[i] = 0;
        if(l == 1)l = 2;
        for(int i = 0; prime[i]<sqrt(r); i++)
        {
            int tmp = prime[i];
            for(int j = l/tmp; j <=r/tmp; j++)
            {
                if(tmp*j>=l&&tmp*j<=r&&j>=2)
                    used[tmp*j-l] = 1;
            }
        }
        int ans1 = maxn,ans2 = -1;
        int pre = -1;
        int a,b,c,d;
        int nu = 0;
        for(int i = 0; i <r-l+1; i++)
        {
            if(!used[i])
            {
                if(nu == 0)
                {
                    nu++;
                    pre = i;
                }
                else
                {
                    if(i-pre < ans1)
                    {
                        ans1 = i-pre;
                        a = pre;
                        b = i;
                    }
                    if(i-pre > ans2)
                    {
                        ans2 = i-pre;
                        c = pre;
                        d = i;
                    }
                    pre = i;nu++;
                }

            }

        }
        if(nu <= 1)
        {
            cout << "There are no adjacent primes."<<endl;
        }
        else
        {
            cout << a+l<<','<<b+l<<" are closest, "<<c+l<<','<<d+l<<" are most distant."<<endl;
        }

    }


    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值