题目链接
题目大意
求两个数字之间,所有两个相邻素数之差最大最小
思路
【主线】
找出所有的素数,再一个一个计算差值的最大最小。
【问题】
数字的最大范围是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,要不之后会有没注意到的错误