蓝桥杯 Java B 组之简单数学问题(素数判断、最大公约数)

embedded/2025/2/15 21:47:18/

Day 4:简单数学问题(素数判断、最大公约数)

数学问题在蓝桥杯中非常重要,尤其是数论基础、数学优化、边界处理等知识。本日的学习目标:

  • 素数判断(Prime Number)
  • 最大公约数(Greatest Common Divisor,简称 GCD)
  • 数学思维转换与优化


 一、素数(Prime Number)

 1. 什么是素数?

**素数(质数)**是指 大于 1,并且只有 1 和 自身 作为因子的整数

通俗定义:大于1的自然数,除了1和它本身外,不能被其他数整除。

例子:2(最小的素数)、3、5、7、11等。

非素数(合数):4(能被2整除)、6(能被2和3整除)。

如何判断素数?

试除法:用2到n-1的数逐个试除,若都除不尽,则为素数。

优化1:只需试除到√n(平方根)。

为什么? 如果n能被a整除,那么n = a×b,a和b至少有一个≤√n。

优化2:先排除偶数(除了2)。

例如:

2, 3, 5, 7, 11, 13, 17, 19...

反之,合数是指除了 1 和 自身 之外,还可以被其他整数整除的数,例如:

4 = 2 × 2, 6 = 2 × 3, 9 = 3 × 3...


 2. 直接枚举法(O(n))

思路

  • 2 开始,检查 n 是否能被 2 ~ n-1 中的任何数整除。
  • 如果可以被整除,则 n 不是素数
  • 如果没有任何数能整除 n,则 n 是素数。

代码实现

public class PrimeNumber {

    public static boolean isPrime(int n) {

        if (n < 2) return false;  // 1 不是素数

        for (int i = 2; i < n; i++) {  

            if (n % i == 0) return false;  // 有因子,非素数

        }

        return true;

    }

    public static void main(String[] args) {

        System.out.println(isPrime(7));  // true

        System.out.println(isPrime(10)); // false

    }

}

时间复杂度 O(n),如果 n 很大(例如 10^9),会非常慢 ❌


3. 优化:遍历到 sqrt(n)(O(√n))

优化思路

  • 任何合数 n 必然可以写成两个因子的乘积: n=a×b
    • 如果 a > sqrt(n),则 b < sqrt(n)。
    • 也就是说,如果 n 有因子,其中至少有一个 ≤ sqrt(n)
    • 因此,我们只需遍历 2 ~ sqrt(n),若 n 不能被其中任何数整除,则 n 是素数。

代码优化

public class OptimizedPrime {

    public static boolean isPrime(int n) {

        if (n < 2) return false;

        if (n == 2) return true;  // 2 是唯一的偶数素数

        if (n % 2 == 0) return false;  // 偶数直接返回 false

        int sqrt = (int) Math.sqrt(n);

        for (int i = 3; i <= sqrt; i += 2) {  // 只检查奇数

            if (n % i == 0) return false;

        }

        return true;

    }

    public static void main(String[] args) {

        System.out.println(isPrime(97));  // true

        System.out.println(isPrime(100)); // false

    }

}

时间复杂度 O(√n),对于 n=10^9 级别问题,能高效处理 ✅


 4. 练习题:区间内素数

题目描述

输入两个整数 `a, b`,输出 `[a, b]` 范围内所有的素数。

代码

import java.util.Scanner;

public class PrimeRange {

    public static boolean isPrime(int n) {

        if (n < 2) return false;

        for (int i = 2; i * i <= n; i++) {

            if (n % i == 0) return false;

        }

        return true;

    }

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        int a = scanner.nextInt();

        int b = scanner.nextInt();

        for (int i = a; i <= b; i++) {

            if (isPrime(i)) {

                System.out.print(i + " ");

            }

        }

    }

}

时间复杂度 O(n√n)


 二、最大公约数(Greatest Common Divisor, GCD)

 1. 什么是最大公约数?

通俗定义:两个数都能被整除的最大正整数。

例子:12和18的最大公约数是6。

应用场景:分数化简(如12/18 → 2/3)。

1. 直接枚举法(O(n))

思路

  • 枚举 1 ~ min(a, b),找到 a 和 b 的最大公因数。

代码

public class GCD {

    public static int gcd(int a, int b) {

        int result = 1;

        for (int i = 1; i <= Math.min(a, b); i++) {

            if (a % i == 0 && b % i == 0) {

                result = i;

            }

        }

        return result;

    }

    public static void main(String[] args) {

        System.out.println(gcd(18, 24));  // 输出 6

    }

}

时间复杂度 O(n),如果 a 和 b 很大,计算会很慢 ❌


 2. 欧几里得算法(辗转相除法,O(logn))

 欧几里得算法(辗转相除法)

核心思想:用较大数除以较小数,用余数替换较大数,直到余数为0,最后的非零余数就是GCD。

数学原理:gcd(a, b) = gcd(b, a % b)。

例子:gcd(48, 18) → gcd(18, 12) → gcd(12, 6) → gcd(6, 0) → 6。

 数学推导

  • 最大公约数定理: GCD(a,b)=GCD(b,aGCD(a, b) = GCD(b, a % b)
  • 终止条件: GCD(a,0)=aGCD(a, 0) = a

代码(递归实现)

public class EuclideanGCD {

    public static int gcd(int a, int b) {

        return (b == 0) ? a : gcd(b, a % b);

    }

    public static void main(String[] args) {

        System.out.println(gcd(18, 24));  // 输出 6

    }

}

代码(迭代实现,防止递归栈溢出)

public class IterativeGCD {

    public static int gcd(int a, int b) {

        while (b != 0) {

            int temp = a % b;

            a = b;

            b = temp;

        }

        return a;

    }

    public static void main(String[] args) {

        System.out.println(gcd(18, 24));  // 输出 6

    }

}

时间复杂度 O(log n),适用于大数计算 ✅


 三、蓝桥杯数学题常考点

考点

典型题目

优化技巧

素数判断

判断素数

遍历到 sqrt(n),跳过偶数

素数筛选

找 1~N 内的素数

埃拉托色尼筛法 O(n log log n)

最大公约数

求 GCD

欧几里得算法 O(log n)

最小公倍数

求 LCM

LCM(a, b) = (a * b) / GCD(a, b)


 四、蓝桥杯中的常考点和易错点

常考点:
素数判断:试除法和优化到平方根的判断方法。
最大公约数:辗转相除法(欧几里得算法)。
数学模型转换:将实际问题转化为数学模型,通过数学公式或算法求解。
易错点:
边界条件:容易忽略边界条件,如1不是素数。
循环逻辑:在试除法中,循环范围容易写错,应为2到sqrt(num)。
效率问题:在求最大公约数时,容易忘记辗转相除法的优化,导致代码效率低下。
5. 术语解释
素数(Prime Number):只能被1和自身整除的大于1的自然数。
最大公约数(GCD, Greatest Common Divisor):两个或多个整数共有约数中最大的一个。
辗转相除法(Euclidean Algorithm):通过不断求余数来计算最大公约数的方法。
总结
素数判断:通过试除法和优化到平方根的方法,可以高效判断一个数是否为素数。
最大公约数:使用辗转相除法(欧几里得算法)可以快速求解两个数的最大公约数。
数学思维转换:将实际问题转化为数学模型,通过数学公式或算法求解。
蓝桥杯常考点:素数判断、最大公约数、数学模型转换。
易错点:边界条件、循环逻辑、效率问题。

http://www.ppmy.cn/embedded/162511.html

相关文章

深度学习R4周:LSTM-火灾温度预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 任务&#xff1a; 数据集中提供了火灾温度&#xff08;Tem1&#xff09;、一氧化碳浓度&#xff08;CO 1&#xff09;烟雾浓度&#xff08;Soot 1&#xff09;…

游戏引擎学习第99天

仓库:https://gitee.com/mrxiao_com/2d_game_2 黑板&#xff1a;制作一些光场(Light Field) 当前的目标是为游戏添加光照系统&#xff0c;并已完成了法线映射&#xff08;normal maps&#xff09;的管道&#xff0c;但还没有创建可以供这些正常映射采样的光场。为了继续推进&…

DDoS技术解析

这里是Themberfue 今天我们不聊别的&#xff0c;我们聊聊著名的网络攻击手段之一的 DDoS&#xff0c;看看其背后的技术细节。 DoS 了解 DDoS 前&#xff0c;先来讲讲 DoS 是什么&#xff0c;此 DoS 而不是 DOS 操作系统啊。1996年9月6日&#xff0c;世界第三古老的网络服务提供…

Redis 数据类型 Zset 有序集合

有序集合相对于字符串、列表、哈希、集合来说会有⼀些陌⽣。它保留了集合不能有重复成员的特点&#xff0c;但与集合不同的是&#xff0c;有序集合中的每个元素都有⼀个唯⼀的浮点类型的分数&#xff08;score&#xff09;与之关 联&#xff0c;着使得有序集合中的元素是可以维…

基于SSM+uniapp的数学辅导小程序+LW示例参考

1.项目介绍 系统角色&#xff1a;管理员、普通用户功能模块&#xff1a;用户管理、学习中心、知识分类管理、学习周报管理、口算练习管理、试题管理、考试管理、错题本等技术选型&#xff1a;SSM&#xff0c;Vue&#xff08;后端管理web&#xff09;&#xff0c;uniapp等测试环…

Docker 镜像的构建与管理(二)

四、Docker 镜像管理 4.1 镜像的拉取与推送 在 Docker 的世界里&#xff0c;镜像的拉取与推送是与镜像仓库进行交互的基本操作。通过这些操作&#xff0c;我们可以方便地获取所需的镜像&#xff0c;以及将自己构建的镜像分享到仓库中&#xff0c;实现资源的共享与复用。 拉取…

一文深入了解DeepSeek-R1:模型架构

本文深入探讨了 DeepSeek-R1 模型架构。让我们从输入到输出追踪 DeepSeek-R1 模型&#xff0c;以找到架构中的新发展和关键部分。DeepSeek-R1 基于 DeepSeek-V3-Base 模型架构。本文旨在涵盖其设计的所有重要方面。 &#x1f4dd; 1. 输入上下文长度 DeepSeek-R1的输入上下文长…

SpringBoot 统一功能处理

1. 拦截器 引入 上个章节我们完成了强制登录的功能, 后端程序根据Session来判断用户是否登录, 但是实现⽅法是⽐较麻烦的 • 需要修改每个接⼝的处理逻辑 • 需要修改每个接⼝的返回结果 • 接⼝定义修改, 前端代码也需要跟着修改 有没有更简单的办法, 统⼀拦截所有的请求,…