PAT 1007 解析


一、题目详情


问题描述:素数对猜想

让我们定义d_{n}为:d_{n}=p_{n+1}-p_{n}​,其中p_{i}是第i个素数。显然有d_{1}=1,且对于n>1有d_{n}​是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。

现给定任意正整数N(<10^{5}),请计算不超过N的满足猜想的素数对的个数。

输入格式:

输入在一行给出正整数N

输出格式:

在一行中输出不超过N的满足猜想的素数对的个数。

输入样例:

20

输出样例:

4

代码长度限制:16 KB

时间限制:200 ms

内存限制:64 MB


二、题目解析


代码:

#include <stdio.h>
#include <math.h>
#include <malloc.h>
#define LEN sizeof(struct Data)

int main()
{
	/*
	* num:正整数(输入数据)
	* sturct Data:用于存储一系列素数的结构体类型(动态链表节点)
	** int x:结构体变量,用于存储素数
	** struct Data *next:结构体成员变量,用于链接结构体变量
	* struct Data *head, *p1, *p2:用于创建动态链表时所需的结构体指针
	* index:数组input的索引值,index+1为素数的个数
	* sum:存储满足猜想的素数对的数量
	* i,j:循环变量
	*/
	int num;
	int i, j, n;
	int index = -1, sum = 0;
	struct Data
	{
		int x;
		struct Data *next;
	};
	struct Data *head, *p1, *p2;
	//获取正整数(输入数据)
	scanf("%d", &num);
	for(i=2;i<=num;i++)//逐一判别<=num内的每一个整数i
	{
		//判别是否为素数:在2到sqrt(n)之间,如果i能被j整除,为非素数,否则为素数 
		n = (int)sqrt(i);
		for(j=2;j<=n;j++)
			if(i%j == 0)//非素数
				break;
		if(j>n)//素数
		{
			p1 = (struct Data *)malloc(LEN);
			p1->x = i;
			if(index == -1)
				head = p1;
			else
				p2->next = p1;
			p2 = p1;
			index++;
		}
		p2->next = NULL;
	}
	//寻找满足猜想的素数对
	p1 = head;
	while(p1->next != NULL)
	{
		p2 = p1->next;
		if((p2->x - p1->x) == 2)
			sum++;
		p1 = p2;
	}
	printf("%d", sum);
	return 0;
}

提交结果(分数/满分):

20/20

 提示:

1. 判断素数的问题

判别素数的方法有很多,如果采用最常规的方法,测试结果可能会出现超时的问题,例如下述的方法1,就会出现超时问题。

方法1:

相关代码:

for(j=2;j<i;j++)
	if(i%j == 0)//非素数
		break;

运行结果:

测试点5:运行超时

表明:您的程序未能在规定时间内结束程序。 原因在于判别素数的方法过于繁琐。

方法2:(本题采用的方案,但不是最优方案)

相关代码:

n = (int)sqrt(i);
for(j=2;j<=n;j++)
	if(i%j == 0)//非素数
		break;

运行结果,不再赘述。

2. 数组定义的问题

1) 方案一

相关代码如下:

定义静态数组:

int input[10000];

经测试,100000以内的素数个数不超过10000,故数组input的大小固定为10000。

存储素数:

if(j>n)
	input[++index] = i;

输出素数对的数量:

if(index > 0)
	for(i=0;i<index;i++)
		if(input[i+1] - input[i] == 2)
			sum++;
printf("%d", sum);

输入样例1:

20

输出样例1:

4

输出结果:

输入样例2:

100000

输出样例2:

1224

2) 方案二

相关代码如下:

定义指针:

int* input = (int *)malloc(sizeof(int) * (index+1));

存储素数:

if(j>n)
	input[++index] = i;

输出素数对的数量:

if(index > 0)
	for(i=0;i<index;i++)
		if(input[i+1] - input[i] == 2)
			sum++;
printf("%d", sum);

输入样例1:

20

输出样例1:

4

提交结果:

 输入样例2:

100000

输出样例2(PAT平台):

1224

输出样例2(Visual C++ 6.0环境):

注:在Visual C++ 6.0环境下,输出样例2没有任何输出结果,程序异常退出,其原因与存储素数的方式有关。经测试,数组input只能存储945个元素,即最后一个素数为7477。原因不详,高手指点,拜谢!

3) 方案三(本题采用的方案)

相关代码如下:

定义结构体:

struct Data
{
	int x;
	struct Data *next;
};
struct Data *head, *p1, *p2;

存储素数:

if(j>n)
{
	p1 = (struct Data *)malloc(LEN);
	p1->x = i;
	if(index == -1)
		head = p1;
	else
		p2->next = p1;
	p2 = p1;
	index++;
}
p2->next = NULL;

输出素数对的数量:

p1 = head;
while(p1->next != NULL)
{
	p2 = p1->next;
	if((p2->x - p1->x) == 2)
		sum++;
	p1 = p2;
}
printf("%d", sum);

输入样例1:

20

输出样例1:

4

提交结果:

输入样例2:

100000

输出样例2:

1224

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值