1063: 最大公约与最小公倍
时间限制: 1 Sec 内存限制: 128 MB
提交: 17697 解决: 7479
题目描述
输入两个正整数,输出其最大公约数和最小公倍数。
输入
输入两个正整数n和m(n,m<=1000000)。输入保证最终结果在int范围内。
输出
输出两个整数,用空格隔开。表示m和n的最大公约数和最小公倍数。
样例输入
4 6
样例输出
2 12
提示 注意运算过程中的溢出问题
这是一道很基础的题目,用辗转相除法算出最大公约数,然后用公式a*b/(MaxGY)
算出最小公倍数即可。所以我写了如下代码:
#include <stdio.h>
int MaxGY(int m,int n){// 假设m<n
if(m>n){
int temp=m;
m=n;
n=temp;
}
int i=m,max=n;
while(max%i!=0){
i=max%i;
if(i>max){
int temp=i;
i=max;
max=temp;
}
}
return i;
}
int MinGB(int m,int n){
int mingb;
mingb=m*n/MaxGY(m,n);
return mingb;
}
int main()
{
int m,n;
scanf("%d %d",&m,&n);
printf("%d %d",MaxGY(m,n),MinGB(m,n));
return 0;
}
使用样例输出没有出现错误,但是提交却发生了错误:
很明显,oj尝试1000000 1000000这组数据,发生了类型溢出。
于是我添加了如下语句:
double x=a*b;
提交后结果仍然和上图一样。
我通过查书看到double的大小为2^52即4503 5996 2737 0496,只有16位,而x为1 0000 0000 0000,说明错误不在double型变量x身上,而很有可能在于运算过程的数据溢出。
我把有关的数据类型全都改为double,这次没有出错,但是运行时间和内存一定会更大,一定有更好的方法。
我把求最小公倍数的公式改为
mingb=m/MaxGY(m,n)*n;
这次运算过程没有溢出,说明一直都是运算过程的锅。
这样写能成功,证明了乘法有可能溢出,但除法一定不会溢出。
因此同时存在乘法和除法运算的式子里应该先写除法,避免过程溢出。
在这个问题里,这样写没有风险,但是在其他地方这样写仍有可能溢出,保险起见数据类型还是应该改为double以保证风险最小。