poj:2689用筛选法选素数求区间[L,U]的所有素数

//http://poj.org/problem?id=2689

#include <bitset>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;


typedef unsigned int uint;
/*
原理:

1) 2的倍数都是合数(2除外)

2) 给定一个N, N*i(i>1)都是合数

算法:

1) 假设所有数都是素数

2) 2的倍数为合数

3) 设3<=N<=sqrt(U)+1且N为奇数,则N * i(i>1)的倍数为合数
*/
bool* GetPrimeNumbers(uint L, uint U,bool Cands[])
{
	const uint N = U-L +1;
	memset(Cands,1,N);	
	for(uint i = L%2==0?0:1;i<N;i+=2)
	{
		Cands[i] = false;
	}
	uint end = sqrt((double)U)+1;
	for(uint i = 3;i<end;i+=2)
	{
		if(i>=L&&Cands[i-L]==false) //i是合数,不需要继续筛选
			continue;
		uint j = L/i*i;
		if(j<L)
		{
			j+=i;
		}
		if(j==i)
			j+=i;
		for(j = j-L;j<N;j+=i)
		{
			Cands[j] = false;
		}		
	}
	if(L==2)
		Cands[0] = true;
	return Cands;
}

bool GetMinMax(bool * Cands,const uint N,int &C1,int &C2, int&D1,int &D2)
{
	C1 = C2 = D1 =D2 = -1;
	int pre = 0;
	int min = 0;
	int max = 0;
	for(uint i =0;i<N;++i)
	{
		if(Cands[i]==true)
		{
			if(C1 == -1)
			{
				C1 = D1 = i;
			}
			else if(C2 == -1)
			{
				C2 =D2 = i;
				min = max = C2 -C1;
			}
			else
			{
				if(i-pre<min)
				{
					C1 = pre;
					C2 = i;
					min = C2-C1;
				}
				else if(i- pre > max)
				{
					D1 = pre;
					D2 = i;
					max = D2 -D1;
				}

			}
			pre =i;			
		}
	}
	return min != 0;
}

bool GetMinMax(uint L,uint U,int &C1,int &C2, int&D1,int &D2)
{
	if(L<2)
		L=2;
	static uint const SIZE = 10000002;
	static bool Cands[SIZE];
	const uint N = U-L +1;
	GetPrimeNumbers(L,U,Cands);
	if(GetMinMax(Cands,N,C1,C2,D1,D2))
	{
		C1+=L;
		C2+=L;
		D1+=L;
		D2+=L;
		return true;
	}
	return false;
}

int main()
{
	uint L,U;
	while(cin>>L>>U)
	{
		int C1,C2,D1,D2;
		if(GetMinMax(L,U,C1,C2,D1,D2))
		{			
			printf("%d,%d are closest, %d,%d are most distant.\n",C1,C2,D1,D2);
		}
		else
		{
			printf("There are no adjacent primes.\n");
		}
	}
	return 0;
}

原文地址:https://www.cnblogs.com/SammyLan/p/2172471.html