zcmu1022(二分+前缀和+素数筛选)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yu121380/article/details/81905500

1022: Primes on Interval

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 286  Solved: 124
[Submit][Status][Web Board]

Description

You've decided to carry out a survey in the theory of prime numbers. Let us remind you that a prime number is a positive integer that has exactly two distinct positive integer divisors.

Consider positive integers aa + 1, ..., b (a ≤ b). You want to find the minimum integer l (1 ≤ l ≤ b - a + 1) such that for any integer x (a ≤ x ≤ b - l + 1) among l integers xx + 1, ..., x + l - 1 there are at least k prime numbers.

Find and print the required minimum l. If no value l meets the described limitations, print -1.

Input

Everay line contains three space-separated integers a, b, k (1 ≤ a, b, k ≤ 106; a ≤ b).

Output

In a single line print a single integer — the required minimum l. If there's no solution, print -1.

Sample Input

2 4 2

6 13 1

1 4 3

Sample Output

3

4

扫描二维码关注公众号,回复: 2972126 查看本文章

-1

题意:给你一段区间,求在长度为l的所有的子区间都满足在这个子区间里有>=k的素数。比如 6  13  1

6~9有一个素数,

7~10有一个素数,

.......

每个长度为4的子区间都满足有>=k的素数。

解析:因为k在10e6,每一次枚举一个数肯定TLE,所有我们可以二分找。但是怎么找这个数呢?二分枚举每一个数,若这个长度为l的所有子区间都满足有>=k的素数,说明我们可能可以往下枚举,就是r=mid-1.反之亦然。每次二分枚举的数要进行check(),证明在所有的子区间都有>=k的素数。求一段区间有多少素数(素数筛选+前缀和)

#include<bits/stdc++.h>
using namespace std;
 
#define e exp(1)
#define pi acos(-1)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#define mem(a,b) memset(a,b,sizeof(a))
int gcd(int a,int b){return b?gcd(b,a%b):a;}

const int maxn=1000005;

int sum[maxn];
int flag[maxn];
int a,b,k;
void init()
{
	mem(flag,false);
	mem(sum,0);
	for(int i=2; i<=sqrt(maxn); i++)
	{
		if(!flag[i])
		{
			for(int j=i+i; j<=maxn; j+=i)
			{
				flag[j]=true;
			}
		}
	}
	for(int i=2; i<=maxn; i++)
	{
		if(!flag[i])sum[i]=sum[i-1]+1;
		else sum[i]=sum[i-1];
	}
}
	

bool check(int n)
{
	int r=b-n+1;
	for(int i=a; i<=r; i++)
	{
		if(sum[i+n-1]-sum[i-1]<k)return 0;
	}
	return 1;
}

int main()
{
	init();
	while(~scanf("%d%d%d",&a,&b,&k))
	{
		//printf("%d %d**\n",sum[4],sum[0]);
		if(sum[b]-sum[a-1]<k)
		{
			puts("-1");
			continue;
		}
		
		int l=1,r=b-a+1,ans=inf;
		while(l<=r)
		{
			int mid=l+r>>1;
			if(check(mid))
			{
				ans=min(mid,ans);
				r=mid-1;
			}
			else l=mid+1;
		}
		printf("%d\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/yu121380/article/details/81905500