您的位置:首页 > 其它

52-题目1040:Prime Number

2016-03-09 15:16 429 查看
http://ac.jobdu.com/problem.php?pid=1040

题目描述:

Output the k-th prime number.

输入:

k≤10000

输出:

The k-th prime number.

样例输入:
3
7


样例输出:
5
17


我已经把边边角角的算法能节省时间的都节省了,比如把目前已知的素数的结果存储起来,如果下一个测试用例的值小于先前的值,那么可以直接查出结果。但是还是不行,核心的判断是不是素数的算法还是太浪费时间了。(第一种方法)然后我又只判断奇数,节约一半时间,但还是超时。

本题思路如下:

一般素数判断方法常用一下三种:

1、最简单的方法:该算法的思想就是用2~sqrt(N),依次去对N求余,只要有一个余数是0,则N就不是素数。该方法虽然思路简单,但效率太低。故不适合于大范围的素数判断。

2、筛选法:该方法不是用来具体判断一个数是否是素数,而是用于判断一个范围内所有的素数。该方法的原理是:首先生成数组,然后从第一个开始依次标注它的倍数,然后从下一个没有被标注的开始,标注它所有的倍数,这样依次下去,最后没有被标注的都是素数。(本题所推荐采用的方法)

3、素数判断法:任何一个合数都可以表现为适当个素数的乘积的形式,所以我们只用素数去除要判断的数即可,比如要判断100以内的素数,只用2,3,5,7就够了,10000以内的数用100以内的素数判断足以。(该方法效率最高,但适应性不高,只适合不大的数)

注:以上方法并非判断素数全部方法,而且每一种方法都可进一步改进。
第一种方法得知第10000个素数为104729,所以就给了第二种方法的范围。

我的第一种方法(超时,结果正确):

#include<iostream>
#include<fstream>
using namespace std;

int main()
{
int k, i, num, result[10001] = {0}, m = 1;
ifstream cin("data.txt");
while (cin >> k)
{
result[1] = 2;
if (result[k] != 0)
cout << result[k] << endl;
else
{
if (result[m] % 2 == 1)
num = result[m] + 2;
else
num = result[m] + 1;   //从3开始判断
while (1)
{
for (i = 2; i < num; i ++)
{
if (num % i == 0)
break;
}
if (i == num)   //是素数,存储起来
{
m++;
result[m] = num;
if (k == m)
break;
}
num += 2;  //只判断奇数,这样节约一半的时间
}
cout << result[k] << endl;
}
}
system("pause");
return 0;
}


我的第二种方法,AC了:

#include<iostream>
#include<fstream>
using namespace std;
#define MAX 105000
int main()
{
int k, i, j, result[MAX] = { 0 }, count = 0;//全初始化为0,结果中0表示为素数,1表示不是素数
ifstream cin("data.txt");
while (cin >> k)
{
result[0] = 1, result[1] = 1, result[2] = 0;
for (i = 2; i <= MAX; i++)
for (j = 2; j <= MAX && i*j <= MAX; j++)
result[i*j] = 1;
count = 0;
i = 0;
while (count < k)
{
if (result[i] == 0)
count++;
i++;
}
cout << i - 1 << endl;
}
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: