(素数筛)Prime Distance

题目链接

POJ 2689

题目大意

求两个数字之间,所有两个相邻素数之差最大最小

思路

【主线】
找出所有的素数,再一个一个计算差值的最大最小。
【问题】
数字的最大范围是2,147,483,647,达到了十位数,231 = 2,147,483,648,即使是用欧拉筛也会超出时间
【提示】
题目中有句话:“The difference between L and U will not exceed 1,000,000.”说明L和U之间的距离很小
【解决】
已知任何一个合数x都一定会有一个不超过√x的质因子,所以先找出√U之内所有的素数,根据这些素数,筛出L-U之间的素数

代码

#include <iostream>
#include <string.h>
#include <vector>
using namespace std;

const int maxN = (1<<16)+10;  //用位运算来表示,2的16次方为65,536
int prime[maxN];    //记录素数
bool judge[maxN];   //标记已经判断过的数
int len;

void getPrime(int n)  //埃氏筛,不需要用欧氏筛也可以过~~
{     
    len = 0;
    for(int i=2; i<=n; ++i)
    {
        if(judge[i]==false)
            prime[++len] = i;
        for(int j=2; j<=n/i; ++j)
            judge[j*i] = true;
    }
}

bool vis[maxN<<4]; //标记L-U之间的素数,2的20次方为1,048,576,可以包含1,000,000

int main()
{
    getPrime(1<<16); //得到了2~1<<16范围内的素数
    int L,U;
    // cout<<len;
    //len一定要放到外面
    while(cin>>L>>U)
    {
        for(int i=1; i<=(U-L+1); ++i) //L+1编号
        {
            vis[i]=true;
        }
        if(L==1)
            vis[1]=false;
        for(int i=1; i<=len; i++) //
        {
            int t = (L-1)/prime[i]+1; //不能写成(L-1+prime[i])/prime[i]的形式,也会超出范围,55555,或者可以long long t
            for(int j=max(prime[i],t); j<=U/prime[i]; j++)  //一定是除法!!,乘法会超出范围
            //保证了开始判断是不是素数的第一个数是L+1(写个方程一解就xin)
            {
                vis[prime[i]*j-L+1] = false;
            }
        }

        vector<int> record;
        for(int i=1; i<=(U-L+1); ++i)
            if(vis[i])
                record.push_back(L+i-1);
        int l = record.size();
        if(l>=2)
        {
            int rmax=0,rmin=0;  //一定要初始化,以后定义一个数,都初始化为0好了。。。
            int maxx=record[1]-record[0];
            int minn=maxx;
            for(int i=2; i<l; ++i)
            {
                if(record[i]-record[i-1] > maxx)
                {
                    maxx = record[i]-record[i-1];
                    rmax = i-1;
                }
                if(record[i]-record[i-1] < minn)
                {
                    minn = record[i]-record[i-1];
                    rmin = i-1;
                }
            }
            cout<<record[rmin]<<','<<record[rmin+1]<<" are closest, "<<record[rmax]<<","<<record[rmax+1]<<" are most distant."<<endl;
        }
        else
            cout<<"There are no adjacent primes."<<endl;
    }
    return 0;
}

总结

① 这个题RE了不知道多少次,呜呜呜,都是超过了int的范围,所以以后遇到这种大数的一定要注意开大,避免乘法
② 每次都初始化定义的数字==0,要不之后会有没注意到的错误

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值