算法——数论——GCD和LCM

本文介绍了欧几里得算法求解最大公约数的方法,包括辗转相除法的步骤,并展示了如何在C语言中实现。同时提及了最小公倍数的计算和实际问题中的应用,如药物剂量计算和列出最简真分数序列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

GCD(最大公约数)

 1、欧几里得算法

LCM(最小公倍数)

一、试题 算法训练 抗击虫群

二、1011: [编程入门]最大公约数与最小公倍数

三、1123: C语言训练-列出最简真分数序列*


GCD(最大公约数)

  • 整数 a 和 b 的最大公约数是指能同时整除 a 和 b 的最大整数,记为 gcd(a,b)
  • -a的因子和a的因子相同,例如gcd(15,18) = gcd(-15,-18) = 3
  • 性质:

 1、欧几里得算法

  • 用辗转相除法求GCD,即 gcd(a,b)=gcd(b,a mod b)
  • 算法思想:
    • 1、用较大的数 b 除以较小的数 a ,得到余数
    • 2、将较小的数和余数作为新的两个数,重复步骤1,直到余数为0
    • 3、余数为0时的除数即为两数的最大公约数
    • 过程中会保证 b 是较大的数,a 是较小的数
  • 代码逻辑:
    • 如果 a 能够整除 b,那么 b 就是 a 和 b 的最大公约数;
    • 否则,最大公约数即为 b 和 a 除以 b 的余数的最大公约数。
    • 我们重复使用这个逻辑,将原先的 b 替换为余数,并将原先的余数替换为新的 b,直到余数变为 0。此时,b 就是最大公约数。

    • 假如需要求 1997 和 615 两个正整数的最大公约数,用欧几里得算法,是这样进行的:
      1997 ÷ 615 = 3 (余 152)
      615 ÷ 152 = 4(余7)
      152 ÷ 7 = 21(余5)
      7 ÷ 5 = 1 (余2)
      5 ÷ 2 = 2 (余1)
      2 ÷ 1 = 2 (余0)
      至此,最大公约数为1以除数和余数反复做除法运算,当余数为 0 时,取当前算式除数为最大公约数,所以就得出了 1997 和 615 的最大公约数 1。

  • 另外还有两种算法:更相减损术和Stein算法,用得较少
public static int gcd(int a,int b){
    return b!=0 ? gcd(b , a % b) : a;
}

LCM(最小公倍数)

  •  a 和 b 的最小公倍数表示为 lcm(a,b)
  • 推论:gcd(a,b) * lcm(a,b) = ab(具体过程略,该公式为结论,说明了LCM和GCD之间的关系)
public static int lcm(int a,int b){
    return a / gcd(a , b) * b;//如果先作乘法可能会溢出
}

一、试题 算法训练 抗击虫群

 分析:

  • 每次都是加 p 的药物量,不能多不能少,(n+m)% p == 0,而且刚好加满两个容器
  • 要快,即是 p 的数值要尽可能大,但最后一勺 p 不能超出容器
  • 综上,求 n 和 m 的最大公约数,使用欧几里得算法
  • 建议先去系统、完整地学习一下这个知识点,再回来处理题目
package no1_1;
import java.util.*;

class Main {
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        while(sc.hasNextLine()) {
        	int n = sc.nextInt();
            int m = sc.nextInt();
            sc.nextLine();//换行
            int p=gcd(n,m);
            System.out.println(p);
        }
    }
    public static int gcd(int a,int b) {//欧几里得算法计算最大公约数
    	return b!=0?gcd(b,a%b):a;
    }
}

二、1011: [编程入门]最大公约数与最小公倍数

题目描述
输入两个正整数m和n,求其最大公约数和最小公倍数。
输入格式
两个整数
输出格式
最大公约数,最小公倍数
样例输入
5 7
样例输出
1 35


import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int a=scanner.nextInt();
        int b=scanner.nextInt();
        System.out.print(gcd(a,b)+" "+lcm(a,b));
    }
    //最大公约数
    public static int gcd(int a,int b) {
    	return b!=0?gcd(b,a%b):a;
    }
    //最小公倍数
    public static int lcm(int a,int b) {
    	return a/gcd(a,b)*b;
    }
}

三、1123: C语言训练-列出最简真分数序列*

题目描述
按递增顺序依次列出所有分母为40,分子小于40的最简分数。

输入格式

输出格式
分数之间用逗号分开(含最末逗号)

样例输入

样例输出
1/40,3/40,7/40,9/40,11/40,13/40,17/40,19/40,21/40,23/40,27/40,29/40,31/40,33/40,37/40,39/40,

public class Main {
    public static void main(String[] args) {
        for(int i=1;i<40;i++) {
        	if(gcd(i,40)==1) {
        		System.out.print(i+"/"+"40"+",");
        	}
        }
    }
    //求最大公约数
    public static int gcd(int a,int b) {
    	return b!=0?gcd(b,a%b):a;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

戏拈秃笔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值