目录
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;
}
}