描述
小乐乐最近在课上学习了如何求两个正整数的最大公约数与最小公倍数,但是他竟然不会求两个正整数的最大公约数与最小公倍数之和,请你帮助他解决这个问题。
输入描述:
每组输入包含两个正整数n和m。(1 ≤ n ≤ 109,1 ≤ m ≤ 109)
输出描述:
对于每组输入,输出一个正整数,为n和m的最大公约数与最小公倍数之和。
示例1
输入:10 20
输出:30
示例2
输入:15 20
输出:65
我们其实代码可以这样写,但是,会超时(时间复杂度高)
//题中用long long类型,而不用int类型,防止求最小公倍数的时候,数字过大溢出int
#define _CRT_SECURE_NO_WARNINGS
//求两个数最大公约数和最小公倍数的和
#include<stdio.h>
int main()
{
long long m = 0;
long long n = 0;
scanf("%d %d", &m, &n);
//1.最大公约数max
long long max = (m > n) ? n : m;
while (1)
{
if ((m % max == 0) && (n % max == 0)) {
break;
}
max--;
}
//2.最小公倍数min
long long min = (m > n) ? m : n;
while (1)
{
if ((min % m == 0) && (min % n == 0)) {
break;
}
min++;
}
//3.求和
long long sum = max + min;
//4.打印
printf("%lld", sum);
return 0;
}
求最大公约数常用的有两种方法,一是九章算术中的更相减损术:大数减小数直到相等,相等的数即最大公约数,该算法时间复杂度约为O(N);二是欧几里得的辗转相除法:大数除以小数取余数(相当于模运算),直到余数为零时(也即模运算为零时)的除数(也即模数)就是最大公约数,该算法时间复杂度约为O(logN)。
求最小公倍数的方法:原始数据的乘积除以最大公约数。
本题数据偏大,选择时间效率更高的辗转相除法更好,第一次提交没通过,发现一组测试用例的输出竟然是负数,一猜肯定是溢出了,然后把数据类型声明改为long long型:
#define _CRT_SECURE_NO_WARNINGS
//求两个数最大公约数和最小公倍数的和
#include<stdio.h>
int main()
{
long long m = 0;
long long n = 0;
scanf("%lld %lld", &m, &n);
long long m2 = m;
long long n2 = n;
//1.最大公约数max
long long max = 0;
while (max = m2 % n2)
{
m2 = n2;
n2 = max;
}
//2.最小公倍数min
long long min = m * n / n2;
//3.求和
long long sum = min + n2;
//4.打印
printf("%lld", sum);
return 0;
}