描述
小乐乐最近在课上学习了如何求两个正整数的最大公约数与最小公倍数,但是他竟然不会求两个正整数的最大公约数与最小公倍数之和,请你帮助他解决这个问题。
输入描述:
每组输入包含两个正整数n和m。(1 ≤ n ≤ 109,1 ≤ m ≤ 109)
输出描述:
对于每组输入,输出一个正整数,为n和m的最大公约数与最小公倍数之和。
此题用笨方法可以用辗转相除法也可以。关键是要知道一个点:两数的乘积=最大公约数*最小公倍数
数学不好的我本来不知道这个也不能理解,所以百度了一番。
百度上说:最大公约数就两个数的所有相同质数相乘,最小公倍数就是扣除一次所有想同的质数全部相乘,补过来刚好,所以两个数的乘积除以他们的最大公约数是最小公倍数。
然后大概懂得了。
用笨方法写的程序是这样的:先求出来最大公约数,再用公式求出来最小公倍数。
#include<stdio.h>
int main()
{
long long m,n,k;//测试数据太长了,用这个long long
int i;
long long p,q,sum;
scanf("%d%d",&m,&n);
for(i=m;i>=1;i--)//求最大公约数
{
if(m%i==0&&n%i==0)
p=i;
break;
}
k=m*n;
q=k/p;
sum=p+q;
printf("%lld",sum);
return 0;
}
贴个优化后用辗转相除法的代码
#include<stdio.h>
int main()
{
long long m,n,t,k,p;//m、n是输入数字,t为中间变量,k为两数乘积,p为最大公倍数
scanf("%d%d",&m,&n);
k=m*n;
while(n!=0)
{
t=m%n;
m=n;
n=t;
}//m是求出来的最大公约数
p=k/m;
printf("%lld",m+p);
return 0;
}
debug记录:一开始是想要用两个for循环分别求出来最大公约数和最小公倍数来着,但是代码跑起来之后不能得出正确结果。
然后发现是
for(i=m;i>=1;i--)//求最大公约数
{
if(m%i==0&&n%i==0)
{p=i;
break;}
}
这个括号的问题,如果不把break括起来,那么执行一次循环就跳出了。遇到break是直接跳出整个循环!
#include<stdio.h>
int main()
{
long long m,n,k;//测试数据太长了,用这个long long
int i,j;
long long p,q,sum;
scanf("%d%d",&m,&n);
for(i=m;i>=1;i--)//求最大公约数
{
if(m%i==0&&n%i==0)
{p=i;
break;}
}
for(j=m;;j++)
{
if(j%m==0&&j%n==0)
{q=j;
break;}
}
sum=p+q;
printf("%lld",sum);
return 0;
}
这样也可以,但是程序运行时间会很长
OJ题过不了。
所给标准答案又有所不同,从第一个看来用while语句比用for语句要简单一些啊,这个答案不需要用公式也不需要用辗转相除法,大道至简我服了。
#include <stdio.h>
/*
int main()
{
int n = 0;
int m = 0;
scanf("%d%d", &n, &m);
//设max是最大公约数
int max = n>m?m:n;
//设min是最小公倍数
int min = n>m?n:m;
while(1)
{
if(m%max==0 && n%max ==0)
{
break;
}
max--;
}
while(1)
{
if(min%m == 0 && min%n==0)
{
break;
}
min++;
}
printf("%d\n", max+min);
return 0;
}
*/
int main()
{
long long n = 0;
long long m = 0;
long long k = 0;
scanf("%lld %lld", &n, &m);
long long a = n;
long long b = m;
while(k=a%b)//神,这个太简单了!
{
a = b;
b = k;
}
printf("%lld\n", b+m*n/b);
return 0;
}
看到第二种做法,拍案叫绝了已经,太牛逼了。总有人可以想到最简单的办法。加油吧慢慢积累!