文章目录
前言
路漫漫其修远兮,吾将上下而求索。
一、最大公约数
假设输入的两个值为m 与 n ;
方法一:硬解
总所周知,最大公约数一定小于等于输入两个值中的最小值;
倘若 n > m ,那么这两个数的最大公约数一定小于等于 n ; 而最大公约数同时满足被 n 与 m 整除;
故而其代码如下:
#include<stdio.h>
int main()
{
int n = 0;
int m = 0;
while (scanf("%d %d", &n, &m)!= EOF)
{
int max = n > m ? n : m;
int min = n < m ? n : m;
//最大公约数
int gcd = min;
while (1)
{
if (n % gcd == 0 && m % gcd == 0)
break;
gcd--;
}
printf("%d\n", gcd);
}
return 0;
}
方法二:辗转相除法
辗转相除法又称为欧几里得算法,用于计算两个非负整数m,n的最大公约数。
1、图形理解:
例如:需求 624 与 1404 的最大公约数;如下图所示:
将数据 624 与 1404 转换成一个矩形而要被一个最大的正方形填充;
在上图中可以清楚地发现,将短边在长边中组成正方形,不看正方形部分于是乎就又形成了一个新的长方形,又在这个新长方形中用短边组成长方形来填充……直到所有面积均被划分地正方形填充,那么此正方形便是填充这个长方形的最大正方形;(看下图可能会明显一点)
转换成数学语言就是将余数除以被除数(余数一定小于被除数)得到的余数再除以上一个式子的被除数;
体现在上图中就是不停地在长边中划分短边的正方形……一直重复直到长边完全被短边划分;那么此时的短边正方形便是填充原矩形的最大正方形;
那么体现成数学公式便为:
2、公式理解:
默认 a,b 为整数,而求a ,b 的最大公约数;
(a,b)-->求 a,b 的最大公约数(a,b)
本质原理:a/b=q…r
如果有两个整数a,b 便会存在唯一的一个整数q和r,满足式子 a/b=q...r
经过上面图形的启发,我们可得知:(a,b)=(b,r)
如何验证这个公式呢?
由a/b=q…r,可得a=b*q+r;以及r=a-b*q;
- 假设(a,b) = d1; 则可以得到 a= d1*m,b=d1*n,其中(n,m)=1,即m与n 互质;存在n与m均属于整数那么可知:r=d1*m -di*n*q= d1(m-ng);
- 假设 (b,r) =d2;则可以得到 b=d2*m,r=d2*n,其中(m,n)=1,存在n与m均属于整数;那么可知:a=d2*m*q+d2*n= d2*(m*q+n)
而又存在(a , b, c, d)=((a,b),c, d);所以(a, b,r )=((a,b),r)=( a,(b,r));
- ((a,b),r)=(d1,r)=(d1,d1(m-ng))=d1;因为m,n,g必为整数,所以 m-ng 必为整数,故而其最大公约数为d1;
- (a,(b,r))=(a,d2)=(d2*(m*g+n),d2)= d2 ;
然而a br这三个整数只存在唯一的最大公约数,故而 d1=d2;
即(a,b)=(b,r)得以验证
即存在:
代码如下:
//辗转相除法
#include<stdio.h>
int main()
{
int n = 0;
int m = 0;
int gcd = 0;
while (scanf("%d %d", &m, &n) != EOF)//多组输入
{
while (m%n)//
{
int c = m % n;
m = n;//被除数当作除数
n = c;//余数当作被除数
}
//当循环停止时,即计算下去无余数时此时的被除数便为最大公约数
gcd = n;
printf("最大公约数为%d\n", gcd);
}
return 0;
}
代码运行结果如下:
二、最小公倍数
假设输入的两个值为m 与 n ;
方法一:硬解
可知,最小公倍数的一定小于等于两数之积而大于等于两数中的较大值;
代码如下:
//最大公倍数
#include<stdio.h>
int main()
{
int m = 0;
int n = 0;
while (scanf("%d %d", &m, &n) != EOF)
{
int lcm = n > m ? n : m;
while (1)
{
if (lcm % n == 0 && lcm % m == 0)
break;
lcm++;
}
printf("最小公倍数为:%d\n", lcm);
}
return 0;
}
代码运行结果如下:
方法二:巧解
在得知最大公约数的情况下满足 : m*n = 最大公约数*最小公倍数;
为什么呢?
如下图:
假设 m = 76x , n = 27x ;那么可知 m*b = 76* x * 27 *x;
而最小公约数为 x ,最大公倍数为 76*27*x; --> 所以得知 m*n = 最大公约数*最小公倍数;
代码如下:
#include<stdio.h>
int main()
{
int n = 0;
int m = 0;
int gcd = 0;
int lcm = 0;
while (scanf("%d %d", &m, &n) != EOF)
{
//最大公约数
int i = m;//保护 m,n
int j = n;
while (i % j)
{
int ret = i % j;
i = j;
j = ret;
}
gcd = j;
//最小公倍数
lcm = (n / gcd) * (m / gcd) * gcd;
printf("最小公倍数为:%d", lcm);
}
return 0;
}
代码运行结果如下:
总结
假设需求m,n 的最大公约数与最小公倍数;
最大公约数:硬解;辗转相除法
最小公倍数:硬解;巧解(辗转相除法+原理:m*n = 最大公约数*最小公倍数)