本题要求两个给定正整数的最大公约数和最小公倍数。
输入在一行中给出两个正整数M和N(≤1000)。
在一行中顺序输出M和N的最大公约数和最小公倍数,两数字间以1空格分隔。
511 292
73 2044
目录
PTA用直接解法
扩展:
更相减损法
辗转相除法:
最大公约数:如果数a能被数b整除,a就叫做b的倍数,b就叫做a的约数。即:
如果两个数a和b的最大公约数是c,那么c能整除a和b,且没有比c更大的数能整除a和b。
最小公倍数:最小公倍数是指两个或多个整数公有的倍数中最小的一个。即:
如果两个数a和b的最小公倍数是c,那么c是a和b的倍数,且没有比c更小的数是a和b的倍数。
我脑海里的第一种基础解法思路:直接暴力求解,首先要知道,最小公约数一定比两个数都要小,所以先判断哪个数比较小,减少代码运算量。然后慢慢减小除数,直到算出第一个余数为0的结果,那么这个除数就是最大公约数。
而如何求最小公倍数呢?按照同样的思路,找出两个数里较大的数,慢慢增加这个数,直到这个数可以整除两个输入数。
#include
int main(){
int m,n,i;
int temp = 0;
scanf("%d%d",&m,&n);
temp=(mn)?m:n;//改变temp为较大的那个数,以下开始求最小公倍数
while(1){
if(temp%m==0&&temp%n==0)//条件与求最大公约数恰好相反
break;
temp++;
}
printf("%d",temp);
return 0;
}
这个已经足以实现PTA通过了。接下来扩展讲一些知识点。
上面的代码过于直接,如果遇到一些特殊的数字的话,代码运算量比较大。
更相减损法是一种用于计算两个整数最大公约数的算法。这种方法的基本思想是:不断用较大的数减去较小的数,然后用新的差值替换原来的较大数,继续这个过程,直到最后两个数相等。在这个相等的时候,两个数就是它们的最大公约数。
以下是代码实现
#include
// 函数声明,用于计算两个数的最大公约数
int gcd(int a, int b) {
// 如果b不为0,则继续用b和a的余数进行递归调用
return b != 0 ? gcd(b, a % b) : a;
}
int main() {
int num1, num2;
// 用户输入两个整数
printf("请输入两个整数:");
scanf("%d %d", &num1, &num2);
// 计算并输出最大公约数
printf("最大公约数为:%d\n", gcd(num1, num2));
return 0;
}
在这个代码中,gcd函数采用了递归的方式来不断地用较大的数减去较小的数,直到余数为0。这个时候,递归调用栈会回到最初的调用,此时的参数a就是两个数的最大公约数。
需要注意的是,更相减损法相比于其他算法如欧几里得算法,其效率并不是最高的,但是它的思想简单且易于理解。在实际应用中,如果对效率要求不是特别高,使用更相减损法是一个不错的选择
再再扩展一下,代码中提到的递归。
递归
指的是一个函数直接或间接地调用自身。
辗转相除法,又称欧几里得算法,是一种高效计算两个整数最大公约数(GCD)的方法。这种方法的基本思想是:用两个整数相除,然后用除数去除被除数,然后用新的被除数去除新的除数,重复这个过程,直到最后余数为0。最后一个非0余数就是两个数的最大公约数。
#include
// 函数声明,用于计算两个数的最大公约数
int gcd(int a, int b) {
// 辗转相除法的实现
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
int main() {
int num1, num2;
// 用户输入两个整数
printf("请输入两个整数:");
scanf("%d %d", &num1, &num2);
// 计算并输出最大公约数
printf("最大公约数为:%d\n", gcd(num1, num2));
return 0;
}
我比较习惯直接用,写着更加简单:
#include
int main()
{
int x = 0, y = 0;
int tmp = 0;
printf("请输入两个数字:");
scanf("%d%d",&x,&y);
while ( y != 0)//辗转相除法
{
tmp = x % y;//x变成两个数字中较大的数字
x = y;
y = tmp;//y被替换成第三个数字
}
printf("最大公约数是:%d\n", x);
return 0;
}