Information
- ID
- 1542
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 7
- Tags
- # Submissions
- 119
- Accepted
- 27
- Uploaded By
这道题算是一个比较综合的问题了,不仅需要用素数筛找出素数,还要用二分法找出对应的区间,在二分的过程中,可以将0和b-a作为搜索的区间边界,使用二分法依次遍历,来找到满足条件最小的l,即可找到正确的答案。
其中有些比较坑的情况,比如2 3 1这种情况,1个素数就能满足条件~。
参考代码:
#include<stdio.h>
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
const long long N=1000010;
int prime[N]={0},num_prime=0;
int A[1000100]={0};
int a,b,k;
bool isNotPrime[N]={true,true};
//判断当前l的值是否满足条件
int check(int l)
{
int flag=1;
for (int i=a;i<=b-l;i++)
{
if (A[i+l]-A[i-1]<k)
{
flag=0;
return 0;
}
}
return 1;
}
//使用二分法寻找l
int erfen(int left,int right)
{
int mid;
while(left+1<right)
{
mid=(left+right)/2;
int S;
S=check(mid);
if (mid==b && S==0) //找不到满足条件的情况,返回错误
{
return -1;
}
if (S==1) //当前满足条件,向更小的方向寻找
{
right=mid;
}
else //当前不满足条件,向更大的方向寻找
{
left=mid;
}
}
return right;
}
//欧拉筛寻找素数
void panprime()
{
long long i,j;
for (i=2;i<=N;i++)
{
if(!isNotPrime[i])
{
prime[num_prime++]=i;
}
for (j=0;j<num_prime && i*prime[j]<N ;j++)
{
isNotPrime[i*prime[j]]=true;
if (!(i%prime[j]))
{
break;
}
// printf("I:%d J:%d\n",i,j);
}
}
}
int main()
{
int ANS=0;
panprime();
//使用前缀和处理,记录从1开始的素数的数量
for (int i=0;i<=N;i++)
{
if (isNotPrime[i]==false)
{
A[i]=A[i-1]+1;
}
else
{
A[i]=A[i-1];
}
}
scanf("%d %d %d",&a,&b,&k);
int s=b-a+1;
//k比s大是不可能的,直接输出-1
if (k>s)
{
printf("-1\n");
return 0;
}
int ans;
ans=erfen(0,s)+1;
//起点和终点完全一样的时候,特殊处理
if (a==b)
{
ans=ans-1;
if (isNotPrime[a]==true)
{
ans=-1;
}
}
//2 3 1这种连续的素数的情况,特殊处理
if (a==2 && b==3 &&k==1)
{
ans=1;
}
if (ans>(b-a+1))
{
ans=-1;
}
printf("%d\n",ans);
return 0;
}
By signing up a 追梦算法网 universal account, you can submit code and join discussions in all online judging services provided by us.