POJ 2689 Prime Distance

本文介绍了一种有效的算法来解决在指定区间内寻找最小和最大相邻素数差的问题。通过预先筛选出一定范围内的所有素数,再利用这些素数快速筛选出指定区间内的素数,从而实现高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://poj.org/problem?id=2689

题目描述:

      给定两个整数a,b,最大能够到int(4字节)的最大值,现在这个区间[a,b]中,求两个相邻素数,它们的差最小,再求两个相邻的素数,它们的差最大。如果区间里小于两个素数,则输出There are no adjacent primes.

     这里基本思想还是很简单,将[a,b]之间的素数筛出来,区间素数筛选,则先筛出一部分素数,然后再用这些素数去筛这个区间的素数。筛完素数之后,扫一遍就能得到结果了。

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

const int MAXM = 1e6+5 ;
const int MAXN = 47000 ;
long long basePri[MAXN], pri[MAXM], baseNum, num ;
bool bp[MAXN], p[MAXM] ; 

void getBasePri(){
	baseNum = 0 ;
	for( int i = 2; i < MAXN; i++ ){
		bp[i] = true ;
	}
	for( int i = 2; i < MAXN; i++ ){
		if( bp[i] ){
			for( int j = 2*i; j < MAXN; j += i ){
				bp[j] = false ;
			}
		}
	}
	for( int i = 2; i < MAXN; i++ ){
		if( bp[i] )	basePri[baseNum++] = i ;
	}
}
//
void getPrim(int x, int y){
	num = 0 ;
	if( y <= MAXN ){
		for( int i = x; i <= y; i++ ){
			if( bp[i] )	pri[num++] = i ;
		}
	}
	else{	
		for( int i = 0; i < MAXM; i++ ){
			p[i] = true ; 
		}
		for( int i = 0; i < baseNum && basePri[i]*basePri[i] <= y; i++ ){
			long long times = x / basePri[i] ;
			if( x % basePri[i] != 0 )	times++ ;
			if( times <= 1 )	times++ ;
			while( times*basePri[i] <= y ){
				p[times*basePri[i]-x] = false ;
				times++ ;
			}	
		}	
		for( int i = 0; i <= y-x; i++ ){
			if( p[i] )	pri[num++] = i+x ;
		}
	}
}
//
int main(){
	//freopen("1234.in","r",stdin) ;
	getBasePri() ;
	int l, u ;
	while( scanf("%d%d",&l,&u) != EOF ){
		getPrim(l,u) ;
		if( num <= 1 ){
			printf("There are no adjacent primes.\n") ;
			continue ;
		}
		int min = pri[1]-pri[0], minL = pri[0], minR = pri[1] ;
		int max = min, maxL = minL, maxR = minR ;
		for( int i = 2; i < num; i++ ){
			int tmp = pri[i]-pri[i-1] ;
			if( tmp < min ){
				minL = pri[i-1] ;
				minR = pri[i] ;
				min = tmp ;
			}
			if( tmp > max ){
				maxL = pri[i-1] ;
				maxR = pri[i] ;
				max = tmp ;
			}
		}
		printf("%d,%d are closest, %d,%d are most distant.\n",minL,minR,maxL,maxR) ;
	}		
	return 0 ;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值