1007 素数对猜想 (20 分)
题目描述:
让我们定义dn 为:dn =Pn+1 −Pn ,其中Pi 是第i个素数。显然有d1 =1,且对于n>1有dn 是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。
现给定任意正整数N(<10^5 ),请计算不超过N的满足猜想的素数对的个数。
输入格式:
输入在一行给出正整数N。
输出格式:
在一行中输出不超过N的满足猜想的素数对的个数。
输入样例:
20
输出样例:
4
解题思路:
根据题意,素数对就是差为2的两个素数。由于除了2之外的所有素数都是奇数,所以求 <= N 的所有素数对的个数就是求 <= N 的奇数序列中有几个相邻的素数对。
本题的另一个考点就是如何判断一个数是否为素数。 判断一个数是否是素数有多种方法,最常见的就是按照素数的定义(只能被 1 和 其自身 整除)。
代码:
def main():
n = int(input())
# 接收输入的整数
answer = 0
temp = 3
# 奇素数序列的首个元素
front = True
end = False
# front 和 end 非别表示两个相邻的奇数是否是素数,
# 当 front == True and end == True 的时候就找到了一个素数对。
while temp + 2 <= n:
temp += 2
# 每次循环 temp + 2,变为下一个奇数
if isPrime(temp):
#如果这个奇数是素数, end = True
#注意循环从5开始,前一个奇数是3,所以front的初始值设置为True
end = True
if front and end:
#front == True and end == True 的时候就找到了一个素数对
answer += 1
front = end
end = False
# 在下一次循环之前,将front的值改为刚刚判断过的,把end的值设置为False
print(answer)
def isPrime(x):
# 判断x是否是素数
if x == 2 or x == 3 or x == 5 or x == 7:
# < 9 的奇数直接判断
return True
if x <= 1 or x % 2 == 0:
# 非正整数或者偶数都不是奇数
return False
boundary = int(x ** 0.5) + 1
# 素数判断的边界是 根号x , 稍微放大一点便于处理边界值。如 x == 9时,为了使
# 循环的条件能够满足,需要boundary 稍大一点。
"""
x ** 0.5 就是对 x 开根号,**表示幂运算。
为什么判断到 根号x 就行了呢? 举个例子,3 < 15 ** 0.5 < 4, 我们只需要
判断到 4(实际上到3即可,为了偷懒起见,我们可以稍微放大一点判断的范围)。
因为 15 == 3 * 5 , 既然 15 能被3整除那它就不是素数,而15能否被5整除的
判断是不必要的。
"""
#循环判断从 9 开始的各个奇数是否能被除了 1 和 它自身之外的奇数整除。
for y in range(3, boundary + 1, 2):
if x % y == 0:
# 如果能被整除,不是素数
return False
# 不能被别的数整除,是素数
return True
if __name__ == '__main__':
main()
- C++ Version:
#include <iostream>
#include <math.h>
using namespace std;
bool isPrime(int );
int main(){
//freopen("in.txt", "r", stdin);
int N;
cin >> N;
int answer = 0, tmp = 3;
bool pre = false, now = false;
while (tmp <= N){
if (isPrime(tmp)){
now = true;
}else{
now = false;
}
if(pre && now){
answer += 1;
}
pre = now;
tmp += 2;
}
cout << answer << endl;
return 0;
}
bool isPrime(int x){
if(x <= 1 || x % 2 == 0){
return false;
}
if(x == 3 || x == 5 || x== 7 ){
return true;
}
int bound = int(sqrt(x) + 1);
for(int i=3; i<=bound; i+=2){
if(x % i == 0){
return false;
}
}
return true;
}
- Java Version:
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int N = in.nextInt();
in.close();
// 接收输入的正整数
boolean pre = false;
boolean now = false;
int answer = 0;
// 记录一共有多少素数对
int tmp = 3;
while(tmp <= N) {
// 更新当前数字是否为素数的标记
if(isPrime(tmp)) {
now = true;
}else {
now = false;
}
if(now && pre) {
// 找到一个素数对
answer += 1;
//System.out.println(tmp-2 + " " + tmp);
}
// 更新前一个数是否是素数的标记
pre = now;
tmp += 2;
}
System.out.print(answer);
}
public static boolean isPrime(int x) {
// 判断输入的正整数是否是素数,只能被1和自身整除的数是素数。
if(x == 2 || x == 3 || x == 5 || x == 7) {
return true;
}else if(x <=1 || x % 2 == 0) {
return false;
}else {
for(int i=3; i<=(int)(Math.sqrt(x)); ++ i) {
if(x % i == 0) {
return false;
}
}
}
return true;
}
}
易错点:
- 正确写出判断素数的算法
- 在判断素数对的时候要尽量减少重复计算避免超时
总结:
- 判断一个数是否是素数是机试中十分常见的问题,所以请务必掌握。
以上程序都是通过全部测试点的,小声说。