52-题目1040:Prime Number

65 篇文章 0 订阅
53 篇文章 0 订阅

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值