【问题】
输入一个整数n,输出1-n之内(包括整数n)的所有质数。
【输入】
输入由一系列的整数构成,每一个整数以Tab键隔开,每一个数表示一个n
【输出】
对于每一个n,输出1-n的所有质数,之间以Tab 键隔开。每一个测试样例另起一行。
【示例输入】
5 11
【示例输出】
2 3 5
2 3 5 7 11
----------------------------------------------------------------------------------------------------------------------------------------------------------------
【解答】
示例代码中采用了两种方法,一种为常规方法,另一种采用埃氏筛选法。具体的介绍可以参考:http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes。你们可以手动修改示例代码中的Methodmethod_temp在不同方法中进行切换,并修改输入n的值(比如:10000000)以比较不同算法之间的运行速率。一般而言当数据量较大时,埃氏筛选法优势明显;数据量较小时区别不大。
下面附上原理图:
【示例代码】
//--------------------------------------【程序说明】-------------------------------------------
// 程序说明:某段连续整数中的所有质数
// 程序描述:
// IDE版本:Visual Studio 2013
// 作者:Arthur Lee
//------------------------------------------------------------------------------------------------
//【1】头文件
#include <fstream>
#include <ctime>
#include <cmath>
using namespace std;
#define TIMER
#define MAXNUMBER 10000001
//【2】函数声明
bool IsPrime(int);
void RangeIsPrime(int);
void InitialData(int);
//【3】定义枚举体,在几种方法中切换
enum Method
{
Normal,
Eratosthenes//埃氏筛选
};
//【4】变量声明
bool flag[MAXNUMBER];//初始化数组,true表示是质数
int main(){
#ifdef TIMER
clock_t start = clock();
#endif // TIMER
ifstream fin("in.txt");
if (fin.fail())
return 1;
ofstream fout("out.txt");
Method method_temp = Method::Normal;//控制使用的方法
int test;
while (!fin.eof())
{
fin >> test;
InitialData(test);//每次检测事例之前,初始化所需的数据
switch (method_temp)
{
case Normal:
for (int i = 1; i <= test; ++i)
{
flag[i] = IsPrime(i);
}
break;
case Eratosthenes:
RangeIsPrime(test);//将需要判断的n传入函数
break;
default:
break;
}
fout << "all primes between 1 and " << test << " are" << "\n";
int count_temp = 0;
for (int i = 1; i <= test; ++i)
{
if (flag[i])
fout << i << "\t";
else
continue;
if (++count_temp == 6){//控制输出格式
count_temp = 0;
fout << "\n";
}
}
}
#ifdef TIMER
clock_t end = clock();
double duration = (double)(end - start);
fout << "runtime : " << duration << "ms" << endl;
#endif // TIMER
fout.close();
return 0;
}
//【5】函数实现
//n为质数时,返回true
bool IsPrime(int n){
//这里未对n<=0 做判断处理
if (n == 1)
return false;
for (int i = 2; i <= (int)sqrt(n); ++i)
{
if (n%i == 0)
return false;
}
return true;
}
void RangeIsPrime(int n){
for (int i = 2; i <= (int)sqrt(n); ++i){
if (!flag[i])
continue;
int j = i + i;
while (j <= n){
flag[j] = false;
j += i;
}
}
}
void InitialData(int n){
for (int i = 0; i <= n; ++i){
flag[i] = true;
}
flag[0] = false;
flag[1] = false;
}