程序要求算一个最大公倍数(是的非常简单的一个题,以至于出错后我都怀疑人生了)
问题在于所求的这个公倍数的数据范围很大,用无符号整形也放不下,必须使用long long整形
如图
原程序如下
unsigned long long min_gong_bei(unsigned long long a, unsigned long long b)
{
unsigned long long max = a * b;
unsigned long long min_num = a < b ? a : b;
unsigned long long ret = max;
for (unsigned long long i = max; i >= a && i >= b; i -= min_num)
{
if (i % a == 0 && i % b == 0)
{
ret = i;
}
}
return ret;
}
int main()
{
unsigned long long sum = 0, num1 = 0, num2 = 0;
scanf("%u%u", &num1, &num2);
sum = max_gong_yue(num1, num2) + min_gong_bei(num1, num2);
printf("%llu", sum);
return 0;
}
经过判断在如下输入例子下出错
通过调试发现
程序最终sum的值正确但输出完全错误,以至于我差点怀疑人生了,就说这么简单的题没理由错啊,原来是被printf坑了
显然%u的极限是4个字节,长长整型就完全不行了
如图
最终修改如下
printf("%llu", sum);
惨痛的教训,大家引以为戒
附加:
正当我洋洋得意的再次提交代码的时候发现超时了...
原代码过于臃肿
一,求公约数,原程序使用了穷举法,修改为欧几里德法
//过程为:
//1,大的数放max_num中、小的数放min_num中,max_num 做被除数, min_num做除数,余数放在tmp中;
//2,若tmp = 0则min_num为最大公约数;
//3,如果tmp != 0则把min_num的值给max_num、tmp的值给max_num;
数学原理证明
(144条消息) 欧几里得算法证明_Einsam0的博客-CSDN博客_欧几里得算法证明
最后代码如下
二,求公倍数
原公倍数从大向小算起来算的太慢还有bug
修改后//只计算最大数的倍数,就可以很快循环完,因为最大公倍数一定是最大数的倍数所以每次循环加最大数,加后判断是不是最小数的倍数
如下
最后提交
竟然又超时了,这都超时,不过比刚才好很多了
超1秒的样子,可能是我电脑不太行,继续优化
通过查找,我们发现了一个很有趣的公式
两个数的乘积等于这两个数的最大公约数与最小公倍数的积
好家伙,上述命题的证明
设两个数分别为A与B,最大公约数为Z,最小公倍数为Y。
那么设 A/Z=a(1),B/Z=b(2)(a与b互为质数)
根据最小公倍数定义Y/A=b(3),Y/B=a(4)
式(1)与(2)等号两边分别相乘得A*B/Z/Z=ab(5)
(3)代入(4)等号两边分别相乘得Y*Y/A/B=ab(6)
将(5)代入(6)得A*B/Z/Z=Y*Y/A/B
根据相关移向得A*A*B*B=Z*Z*Y*Y
两边开方得A*B=Y*Z
最终代码修改如下
过了!