蓝桥云课-小蓝做题

目录

题目链接:

题目:

解题思路:

代码:

问题:

不懂为什么for循环进行相除控制就可以确保每个因子都是质数?

总结:


题目链接:

1.小蓝做题 - 蓝桥云课

题目:

解题思路:

知道使用辗转相处法计算最大公约数,知道最大公倍数==使用a和b的乘积除于最大公约数

另外知道怎么计算某个数的质因数之和

代码:

java 复制代码
 /*out
*Stack Integer ArrayList String StringBuffer peek
*Collections imports LinkedList offer return
*empty polls offerLast pollFirst isEmpty
*List Deque append length HashMap
*return remove boolean continue charAt
*toString static System println nextInt
*Scanner  System  toCharArray
*/
import java.util.*;
public class Main {
    static Scanner sc = new Scanner(System.in);
    public static void main(String[] args) {
        int t=sc.nextInt();
        while(t--!=0){
          slove();
        }
        sc.close();
    }
    public static void slove(){
      int n=sc.nextInt(),tar=sc.nextInt();
      int x=getSum(n);
      int yue=gcd(x,n);
      int lcm=x*n/yue;
      if(lcm==tar){
        System.out.println("YES");
      }else{
        System.out.println("NO");
      }
    }
    //分解某个数的质因数之和
    public static int getSum(int n){
      int x=0;
      for(int i=2;i<=n;i++){
        while(n%i==0){
          x+=i;
          n/=i;
        }
      }
      return x;
    }
    public static int gcd(int a,int b){
      int t;
      while(b!=0){
        t=b;
        b=a%b;
        a=t;
      }
      return a;
    }
}

问题:

不懂为什么for循环进行相除控制就可以确保每个因子都是质数?

任何合数都可以分解为更小的质数的乘积(质因数分解定理)

总结:

一、问题背景与核心需求

"小蓝做题" 是一道融合质因数分解与最小公倍数计算的算法题,其核心需求可拆解为 3 个步骤:

对给定正整数n进行质因数分解,计算所有质因数的和x;

计算x与n的最小公倍数(LCM);

判断该最小公倍数是否等于输入的num,输出YES或NO。

这道题的本质是对 "数论基础操作" 的综合考察,代码通过封装核心逻辑(质因数和计算、最大公约数计算)实现了高效解题。

二、代码整体结构解析

java

运行

import java.util.*;

public class Main {

static Scanner sc = new Scanner(System.in);

public static void main(String[] args) {

int t=sc.nextInt();

while(t--!=0){

slove();

}

sc.close();

}

public static void slove(){

int n=sc.nextInt(),tar=sc.nextInt();

int x=getSum(n);

int yue=gcd(x,n);

int lcm=x*n/yue;

if(lcm==tar){

System.out.println("YES");

}else{

System.out.println("NO");

}

}

// 计算n的质因数之和

public static int getSum(int n){

int x=0;

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

while(n%i==0){

x+=i;

n/=i;

}

}

return x;

}

// 计算最大公约数(GCD)

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

int t;

while(b!=0){

t=b;

b=a%b;

a=t;

}

return a;

}

}

代码采用 **"多测试用例 + 功能模块化"** 的结构,分为 3 个核心模块:

输入处理模块:main方法读取测试用例数T,循环调用slove()处理每组数据;

业务逻辑模块:slove()方法串联 "质因数和计算→最大公约数计算→最小公倍数计算→结果判断" 的全流程;

工具方法模块:getSum()(质因数和)与gcd()(最大公约数)是实现核心逻辑的基础工具。

三、核心工具方法解析:getSum()------ 质因数和的计算

  1. 方法功能

getSum(int n)的作用是对n进行质因数分解,并累加所有质因数的和。例如:

当n=8时,质因数是2、2、2,返回2+2+2=6;

当n=21时,质因数是3、7,返回3+7=10。

  1. 实现原理:"从小到大试除 + 除尽当前因子"

方法通过 **"遍历试除 + 循环除尽"** 的策略,确保所有质因数被累加,且避免合数干扰:

java

运行

public static int getSum(int n){

int x=0;

// 从2开始试除(最小的质数)

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

// 若i能整除n,说明i是n的质因数

while(n%i==0){

x += i; // 累加质因数

n /= i; // 除尽当前质因数(缩小n)

}

}

return x;

}

(1)为什么 "从小到大试除" 能过滤合数?

任何合数都可以分解为更小的质数的乘积(质因数分解定理)。例如:

当i=4(合数)时,若n能被 4 整除,说明n必然能被 2(4 的质因数)整除;

但i=2已经提前遍历过,n中的 2 已被除尽,因此n%4必然不等于 0,自然不会被当作因子累加。

这一特性确保了只有质数能满足n%i==0,因此被累加的i都是质因数。

(2)"循环除尽当前因子" 的作用

内层while循环的作用是将当前质因数的所有出现次数都累加。例如:

当n=12时,质因数是2、2、3:

i=2时,12%2==0→进入循环,x+=2(x=2),n=6;

再次判断6%2==0→x+=2(x=4),n=3;

再次判断3%2≠0→退出循环;

i=3时,3%3==0→x+=3(x=7),n=1;

最终返回7(正确的质因数和)。

  1. 方法的正确性验证

以样例输入中的n=21为例:

i=2:21%2≠0→跳过;

i=3:21%3==0→x+=3(x=3),n=7;

i=4~6:7%i≠0→跳过;

i=7:7%7==0→x+=7(x=10),n=1;

返回10(正确)。

四、核心工具方法解析:gcd()------ 最大公约数的计算

  1. 方法功能

gcd(int a, int b)通过 ** 欧几里得算法(辗转相除法)** 计算a和b的最大公约数(GCD)。例如:

gcd(10,21)=1(10 和 21 互质);

gcd(4,6)=2。

  1. 欧几里得算法的原理

欧几里得算法的核心是:两个数的最大公约数等于其中较小数和两数余数的最大公约数。公式表示为:gcd(a,b) = gcd(b, a%b),直到b=0,此时a就是最大公约数。

  1. 方法的执行过程

以gcd(10,21)为例:

初始:a=10,b=21→b≠0;

t=21,b=10%21=10,a=21;

再次判断:b≠0→t=10,b=21%10=1,a=10;

再次判断:b≠0→t=1,b=10%1=0,a=1;

b=0→返回a=1(正确)。

五、业务逻辑模块解析:slove()------ 全流程串联

slove()方法是代码的 "大脑",负责将工具方法的结果串联起来,完成问题的核心需求:

java

运行

public static void slove(){

// 读取当前测试用例的n和目标num

int n=sc.nextInt(),tar=sc.nextInt();

// 步骤1:计算n的质因数和x

int x=getSum(n);

// 步骤2:计算x和n的最大公约数

int yue=gcd(x,n);

// 步骤3:计算x和n的最小公倍数(LCM = 两数乘积 / 最大公约数)

int lcm=x*n/yue;

// 步骤4:判断LCM是否等于num,输出结果

if(lcm==tar){

System.out.println("YES");

}else{

System.out.println("NO");

}

}

  1. 最小公倍数的计算逻辑

最小公倍数(LCM)的计算公式是:LCM(a,b) = (a * b) / GCD(a,b)

这是数论中的基础公式,原理是:两数的乘积等于它们的最大公约数和最小公倍数的乘积。

  1. 样例输入的全流程验证

我们以样例输入中的第一个测试用例21 210为例,完整模拟流程:

步骤 1:n=21→getSum(21)=10(x=10);

步骤 2:gcd(10,21)=1(yue=1);

步骤 3:lcm=10*21/1=210;

步骤 4:lcm=210 == tar=210→输出YES(与样例一致)。

再以第二个测试用例4 35为例:

步骤 1:n=4→质因数是2、2→getSum(4)=4(x=4);

步骤 2:gcd(4,4)=4(yue=4);

步骤 3:lcm=4*4/4=4;

步骤 4:4≠35→输出NO(与样例一致)。

第三个测试用例105 105:

步骤 1:n=105→质因数是3、5、7→getSum(105)=3+5+7=15(x=15);

步骤 2:gcd(15,105)=15(yue=15);

步骤 3:lcm=15*105/15=105;

步骤 4:105==105→输出YES(与样例一致)。

六、代码的效率与鲁棒性分析

  1. 时间效率

getSum()方法:循环上限是n,但实际由于n被不断缩小,实际遍历次数远小于n;对于n≤1e5的情况,时间复杂度约为O(√n)(优化后可直接将循环上限改为i*i≤n)。

gcd()方法:欧几里得算法的时间复杂度是O(log(min(a,b))),效率极高。

整体时间复杂度:对于T=1e4、n≤1e5的测试用例,代码可在 1 秒内完成,完全满足算法题的时间要求。

  1. 鲁棒性

输入合法性:题目保证输入是正整数,因此无需处理n≤1的情况;

数据范围:代码中使用int类型,对于n≤1e5的情况完全足够(int最大值为 2e9);若n更大,可改为long类型。

七、代码的可扩展性优化

  1. getSum()方法的性能优化

原getSum()方法的循环上限是i≤n,可优化为i*i≤n(减少遍历次数),并在循环结束后处理剩余的质数:

java

运行

public static int getSum(int n){

int x=0;

for(int i=2;i*i <=n;i++){ // 优化循环上限

while(n%i==0){

x+=i;

n/=i;

}

}

if(n>1) x+=n; // 剩余的n是质数

return x;

}

例如n=21时,i只需遍历到4(4*4>7),然后通过n>1累加 7,效率更高。

  1. 支持更大数据范围

若n的范围超过int(如n≤1e18),需将变量类型改为long:

java

运行

public static long getSum(long n){

long x=0;

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

while(n%i==0){

x+=i;

n/=i;

}

}

if(n>1) x+=n;

return x;

}

八、同类问题的延伸与应用

这道题的核心操作(质因数分解、最大公约数 / 最小公倍数计算)是数论类算法题的基础,常见的延伸问题包括:

判断一个数是否为质数:基于质因数分解的逻辑,若getSum(n)==n,则n是质数;

计算数的因数个数:在质因数分解时记录每个质因数的次数,因数个数为 "次数 + 1" 的乘积;

分数的约分:通过最大公约数将分子分母同时除以 GCD,得到最简分数。

九、总结

这道题的代码通过 **"模块化工具方法 + 流程化业务逻辑"** 的设计,清晰地实现了问题的核心需求。其亮点在于:

getSum()方法:利用 "从小到大试除 + 除尽当前因子" 的策略,高效且正确地计算质因数和;

gcd()方法:通过欧几里得算法快速计算最大公约数,为最小公倍数的计算奠定基础;

业务逻辑串联:通过简单的公式计算最小公倍数,并完成结果判断,逻辑清晰易读。

对于初学者而言,这道题是数论基础操作的绝佳练习,掌握其代码逻辑后,可轻松应对同类的数论问题。

相关推荐
f***24111 小时前
Spring Boot接收参数的19种方式
java·spring boot·后端
xunyan62341 小时前
面向对象(下)-设计模式与单例设计模式
java·单例模式·设计模式
啊吧怪不啊吧1 小时前
贪心算法(局部最优实现全局最优)第二篇
大数据·算法·leetcode·贪心算法
艾莉丝努力练剑1 小时前
【C++:C++11收尾】解构C++可调用对象:从入门到精通,掌握function包装器与bind适配器包装器详解
java·开发语言·c++·人工智能·c++11·右值引用
卿雪1 小时前
MySQL【索引】篇:索引的分类、B+树、创建索引的原则、索引失效的情况...
java·开发语言·数据结构·数据库·b树·mysql·golang
CNRio1 小时前
第七章-DockerSwarm:容器集群的‘指挥官‘
java·开发语言·容器
MicroTech20251 小时前
微算法科技(NASDAQ:MLGO)使用区块链和迁移学习技术进行安全的IoT数据传输
科技·算法·区块链
李景琰1 小时前
Java 25+AI+物联网+区块链融合平台:架构设计与企业级实现
java·人工智能·物联网·区块链
追梦者1231 小时前
springboot处理全局返回日期格式,全局处理停用的数据(不返回)
java