PAT (Basic Level) Practice 1007 素数对猜想

题目

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

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

输入格式:

输入在一行给出正整数N

输出格式:

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

输入样例:

20

输出样例:

4

思路&总结

思路(2020-4-9 01:09:00):

1、将N之前的所有素数依次列出来,数一下相邻两个素数差值是2的总共有多少对。
2、老规矩,素数表使用数组保存,方法类似键值对。
*优化点也就是主要的时间消耗点在于素数判断。百度到直接构造素数表的方法应该较快,也就是在一张表中直接踢掉非素数,剩下的就是素数了,时间复杂度是 o ( n ) o(n) o(n)。答案1是用的循环遍历判断有木有因数从而判断是否为素数,时间复杂度是 o ( n 3 2 ) o({n^{\frac{3}{2}}}) o(n23)。答案2.等下想想写不写构造素数表再决定答案2存不存在。

总结(2020-4-9 01:58:11)

1、素数判断循环上限可以使用sqrt(n)提高判断效率。
2、当需要用到连续的多个素数时,可以用构造素数表的方式提高时间效率。
3、使用sqrt(n)需要#include <math.h>
4、memset(void *str, int c, size_t n)str中当前位置到后面的n个字节填充c。可用来做数组初始化.
5、解释二void *memset(void *s, int v, size_t n)包含在<string.h>头文件中,可以用它对一片内存空间逐字节进行初始化。 这里s可以是数组名,也可以是指向某一内在空间的指针;v为要填充的值;n为要填充的字节数;
6、根据https://blog.csdn.net/u011426016/article/details/86559895 的指示,也只能用来处理某些赋值,最好是char类型,int类型容易出错,计组学的好的可以研究一下这个博客,就是涉及到数据结构的物理存储和计算机存储的源码补码反码这些问题了,用来给char赋初始值就完全某门题。
7、根据百度百科 这个,也讲的很仔细,学习。
8、使用memset()需要#include <string.h>

答案1(2020-4-9 01:58:27)

#include <iostream>
#include <math.h>
using namespace std;

int isPrimeNumber(int k)
{
	if (k<=1) return 0;
	int maxDivisor = (int)sqrt(k);
	for (int i = 2; i <= maxDivisor ; i++)
		if(k % i == 0)
			return 0;
	return 1;
}

int main(int argc, char *argv[]) {
	int n;
	cin >> n;
	int primeNumber[n] = {0};
	for (int i = 2; i <= n ; i++)
		if(isPrimeNumber(i)==1) primeNumber[i] = 1;

	int countCouple = 0;
	for (int i = 5; i <= n ; i++)
		if(primeNumber[i] == 1 && primeNumber[i-2] == 1 )
			countCouple ++;
	
	cout << countCouple;
	return 0;
}

答案2(2020-4-9 02:19:42)

测试点5运行时间由16ms缩减为4ms

#include <iostream>
#include <math.h>
using namespace std;

int main(int argc, char *argv[]) {
	int n;
	cin >> n;
	int primeNumber[n+1] = {0};
	
	//createPrimeTable
	for (int i = 2; i < n ; i++)
	{
		if(primeNumber[i]==0)
		{
			int j = 2; 
			for(j = 2 ; j * i <= n ; j++)
				primeNumber[j*i] = 2;//not prime;
		}
	}
	
	//count PrimeCouple
	int countCouple = 0;
	for (int i = 5; i <= n ; i++)
		if(primeNumber[i] == 0 && primeNumber[i-2] == 0 )
			countCouple ++;
	
	cout << countCouple;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值