debug日记1:BC115 小乐乐与欧几里得(辗转相除法求最大公约数和最小公倍数)

描述

小乐乐最近在课上学习了如何求两个正整数的最大公约数与最小公倍数,但是他竟然不会求两个正整数的最大公约数与最小公倍数之和,请你帮助他解决这个问题。

输入描述:

每组输入包含两个正整数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;
}

优化的方法是辗转相除法,啥叫辗转相除法呢,这一篇写得超级清晰的!看的时候注意除和除以的区别就好辗转相除法的原理_哈哈哈哈嘻哈从的博客-CSDN博客_辗转相除法辗转相除法是求最大公约数的一种方法。它的具体做法是:用较小数除较大数,再用出现的余数(第一余数)去除除数,再用出现的余数(第二余数)去除第一余数,如此反复,直到最后余数是0为止。如果是求两个数的最大公约数,那么最后的除数就是这两个数的最大公约数。这个和更相减损术有着异曲同工之处。原理:首先介绍下更相减损术的原理,假设有两个数161和63,我们要求这两个数的最大公因数,不妨假定这个最大公因数为m...https://blog.csdn.net/weixin_43886797/article/details/85569998?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165276827516781818779890%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165276827516781818779890&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-85569998-null-null.142%5Ev10%5Epc_search_result_control_group,157%5Ev4%5Econtrol&utm_term=%E8%BE%97%E8%BD%AC%E7%9B%B8%E9%99%A4%E6%B3%95&spm=1018.2226.3001.4187

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;
}

看到第二种做法,拍案叫绝了已经,太牛逼了。总有人可以想到最简单的办法。加油吧慢慢积累!

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值