「PAT乙级真题解析」Basic Level 1007 (问题分析+完整步骤+伪代码描述+提交通过代码)

[PAT练级笔记] 05 Basic Level 1007

#需求分析#pat考试#c语言#算法

Table of Contents

乙级的题目训练主要用来熟悉编程语言的语法和形成良好的编码习惯和编码规范。从小白开始逐步掌握用编程解决问题。

PAT乙级BasicLevelPractice 1007

问题分析

题目要求: 不超过N的满足猜想的素数对的个数

我们需要解决的问题是:

  1. 不超过N
  2. 满足猜想
  3. 求个数

"不超过N"思路很明确, 就是一个判断 (条件语句) "求个数"的思路明确, 需要记录个数, 然后将记录的个数作为答案 那么, "满足猜想"是指什么? 根据题设中「“素数对猜想”认为“存在无穷多对相邻且差为2的素数”」, "满足猜想"的意思是: 两个数是相邻的素数(即, 两个素数之间没有其他数是素数), 且两个数相差2. 于是, 要判断是否"满足猜想", 就需要做以下这些判断: 1. 一个数是不是素数 2. 一个数+2之后是不是素数

如何判断一个数是不是素数

  • 素数定义: 除了1和自身之外, 没有其他因子
  • 从2开始到值等于这个数本身之前, 如果有任一个整数被这个数整除, 则这个数不是素数.

用伪代码将思路完整描述为如下步骤

  • 对不超过N的正整数x进行如下操作: (涉及循环, 因为N输入之后就固定了, 所以优先选择处理固定次数for循环)
    • 检查x是不是素数;
    • 如果x不是素数, 则不再进行后续操作;
    • 如果x是素数, 则检查x+2是不是素数;
    • 如果x+2是素数, 说明我们找到了一对满足猜想的素数, 记录个数+1;

完整提交代码

/*
问题分析:
题目要求: 不超过N的满足猜想的素数对的个数
 
我们需要解决的问题是:
1. 不超过N
2. 满足猜想
3. 求个数
 
"不超过N"思路很明确, 就是一个判断 (条件语句)
"求个数"的思路明确, 需要记录个数, 然后将记录的个数作为答案
那么, "满足猜想"是指什么?
根据题设中「“素数对猜想”认为“存在无穷多对相邻且差为2的素数”」, 
"满足猜想"的意思是: 两个数是相邻的素数(即, 两个素数之间没有其他数是素数), 且两个数相差2.
于是, 要判断是否"满足猜想", 就需要做以下这些判断:
    1. 一个数是不是素数
    2. 一个数+2之后是不是素数
 
【如何判断一个数是不是素数】
- 素数定义: 除了1和自身之外, 没有其他因子
- 从2开始到值等于这个数本身之前, 如果有任一个整数被这个数整除, 则这个数不是素数.
 
用伪代码将思路完整描述为如下步骤:
对不超过N的正整数x进行如下操作: (涉及循环, 因为N输入之后就固定了, 所以优先选择处理固定次数for循环)
    检查x是不是素数;
    如果x不是素数, 则不再进行后续操作;
    如果x是素数, 则检查x+2是不是素数;
    如果x+2是素数, 说明我们找到了一对满足猜想的素数, 记录个数+1;
*/
 
# include<stdio.h>
# include<math.h>
 
int is_prime_number(int number){
    if (number == 2){
        return 1;
    }
    
    int digit = number % 10;
    
    if (digit != 1 && digit != 3 && digit != 5 && digit != 7 && digit != 9 ){
        return 0;
    }
    
    for(int i = 2; i <= sqrt(number); i++){
        if(number % i == 0){
            return 0;
        }
    }
    return 1;
}
 
int count_number_pair_meet_target_condition(int number){
    /*求出满足给定条件(满足素数对猜想, 且不超过number)的数对个数.
    具体逻辑:
    for (不超过N的正整数x进行如下操作)
        检查x是不是素数;
        如果x不是素数, 则不再进行后续操作;
        如果x是素数, 则检查x+2是不是素数;
        如果x+2是素数, 说明我们找到了一对满足猜想的素数, 记录个数+1;
    */
    int count = 0;
    int checked_is_prime[number+10];
    int size_of_cache = sizeof(checked_is_prime) / sizeof(checked_is_prime[0]);
    for(int i = 0; i < size_of_cache; i++){
        checked_is_prime[i] = -1;
    }
    
    for (int i = 1; i + 2 <= number; i = i + 2){
        if (i == 1){
            continue;
                
        }
        
        if (checked_is_prime[i] == -1){
            checked_is_prime[i] = is_prime_number(i);
        }
        
        if (checked_is_prime[i] == 1){
            if (checked_is_prime[i+2] == -1){
                checked_is_prime[i+2] = is_prime_number(i+2);
            }
            if (checked_is_prime[i+2] == 1){
                count ++;
            }
        }
    }
    
    return count;
}
 
 
int main(){
    
    int number;
    if (scanf("%d", &number) != 1){
        return 1;
    }
    
    int count = count_number_pair_meet_target_condition(number);
    printf("%d", count);
    
    return 0;
}