编程之美---最大公约数问题

简介:

该文出自于编程之美中关于最大公约数问题一章。

任意给定两个数字,得到其最大公约数 GCD(greatest common divisor),如果两个数字都很大怎么解决。

分析:最大公约数早在公元前300年,欧几里得的《几何原本》里就提出了一个高效率算法---辗转相除法。

解法一:

假设f(x,y)表示x,y的最大公约数,取k=x/y,b=x%y,则x=ky+b,如果一个数字能同时整除x,y,那么必能够同时整除b,y;而能够同时整除b,y的数必能够同时整除x,y,即x,y的公约数与b,y的公约数是相同的,其最大公约数也是相同的,则必有f(x,y)=f(y,x%y)(x>=y>0),从而把两个数字的最大公约数转化为求两个更小数字的最大公约数,直到其中一个数字为0,剩下的另一个数字就是两者最大的公约数。

例如: f(42,30) = f(30,12) = f(12,6) = f(6,0) = 6

代码如下:

int gcd(int x,int y)
{
    return (!y)?x:gcd(y,x%y);
}

解法二:

由于辗转相除法中存在一个最大的问题是,取模运算(其中用到了除法运算)是非常昂贵的开销,成为了算法的瓶颈。根据解法一的思路分析,假设一个数能够同时整除x,y,则必能够同时整除x-y,y;而同时能够整除x-y,y的数字也必能够同时整除x,y,即x,y的公约数与x-y,y的公约数相同,其最大公约数也是相同的 即:f(x,y) = f(x-y,y)。这样做就不需要进行大量的去摸运算,而转化为减法运算。

例如:f(42,30) = f(30,12) = f(12,18) = f(12,6) = f(6,6,)=f(6,0) = 6

代码如下:

复制代码
int gcd(int x,int y)
{
    if (x < y)
    return gcd(y,x);
    if (y == 0)
    return x;
    return gcd(x-y,y);
}
复制代码

解法三:

解法一处理大整数整除问题比较复杂,解法二处理虽然将大整数问题除法转换为减法运算,降低了复杂度,但是他的问题在于减法迭代次数太多了。最好的方法就是解法一和解法二结合使用。

分析: 对于 y和x来说,如果y = k*y1, x = k*x1。那么有 f(y,x)=k*(y1,x1)。另外,如果x = p*x1,假设p是素数,且y%p!=0(即y不能够被p整除),那么f(x,y)=f(p*x1,y)=f(x1,y);根据以上两点,我们可以对算法进行改进,最简单的就是取素数2,因为对于素数2同时可以转化为移位运算,避免大整数除法。

取p = 2;

若:x,y均为偶数, f(x,y) = 2*f(x/2,y/2)=2*f(x>>1,y>>1)

若:x为偶数,y为奇数,f(x,y)=f(x/2,y) = f(x>>1,y);

若:x为奇数,y为偶数,f(x,y)=f(x/2,y) = f(x,y>>1);

若:x,y均为奇数,f(x,y)=f(y,x-y),那么就存在f(x,y)=f(y,x-y)之后,(x-y)是一个偶数,下一步一定会有除以2的操作了。

因此这样的复杂度为 O(log2(max(x,y)));

例如:

f(42,30) = f(1010102,111102)

      =2*f(101012,11112)

      =2*f(11112,1102)

      =2*f(11112,112)

      =2*f(11002,112)

      =2*f(112,112)

              =2*f(02,112)

     = 2*112

       =6

代码如下:

复制代码
//奇数 偶数判断
bool isEven(int n)
{
    return (n&1)?false:true;
}
//高效率gcd
int gcd(int x,int y)
{
    if (x<y)
    return gcd(y,x);
    if (y == 0)
    return x;
    if(isEven(x))
    {
        if(isEven(y))
            return (gcd(x>>1,y>>1)<<1);
        else return gcd(x>>1,y);
    }else
    {
        if(isEven(y))
            return gcd(x,y>>1);
        else return gcd(y,x-y);
    }
}
复制代码

 







本文转自NewPanderKing51CTO博客,原文链接:http://www.cnblogs.com/newpanderking/p/3953223.html ,如需转载请自行联系原作者



相关文章
|
11月前
|
物联网 调度 vr&ar
鸿蒙HarmonyOS应用开发 |鸿蒙技术分享HarmonyOS Next 深度解析:分布式能力与跨设备协作实战
鸿蒙技术分享:HarmonyOS Next 深度解析 随着万物互联时代的到来,华为发布的 HarmonyOS Next 在技术架构和生态体验上实现了重大升级。本文从技术架构、生态优势和开发实践三方面深入探讨其特点,并通过跨设备笔记应用实战案例,展示其强大的分布式能力和多设备协作功能。核心亮点包括新一代微内核架构、统一开发语言 ArkTS 和多模态交互支持。开发者可借助 DevEco Studio 4.0 快速上手,体验高效、灵活的开发过程。 239个字符
964 13
鸿蒙HarmonyOS应用开发 |鸿蒙技术分享HarmonyOS Next 深度解析:分布式能力与跨设备协作实战
|
10月前
|
人工智能 安全 数据中心
首个全球AI出口管制规则出台,中国AI路在何方?
在CES 2025上,英伟达宣布Blackwell芯片全面投产,GB200芯片为大语言模型推理带来30倍性能提升,成本和能耗降低25倍。然而,1月13日白宫公布的“临时最终规则”对AI芯片出口进行严格限制,引发市场悲观情绪。新规将全球分为三级,中国大陆被列为Tier 3,面临先进芯片进口禁令和模型权重管控,加剧了中国AI产业的挑战。尽管如此,华为云、科大讯飞等企业通过自主创新,如昇腾AI云服务,提供了稳定可靠的算力解决方案,展现了中国科技企业的韧性和创新精神,推动大模型生态的发展。
251 16
|
Cloud Native Java 持续交付
云原生时代的微服务架构实践
在数字化转型的浪潮中,云原生技术已成为推动企业IT现代化的重要力量。本文旨在通过深入浅出的方式,探讨在云原生环境下微服务架构的实践要点,从基础概念到具体实现,带领读者逐步理解并掌握如何在云计算平台上构建、部署和管理高效的微服务应用。我们将一起探索容器化、持续集成/持续部署(CI/CD)等关键技术,并通过实际案例分析,揭示微服务架构带来的业务价值和挑战。无论您是云原生技术的新手,还是希望深化理解的开发者,这篇文章都将为您开启一段云上之旅。
204 1
|
弹性计算 运维 自然语言处理
阿里云OS Copilot测评:重塑Linux运维与开发体验的智能革命
阿里云OS Copilot巧妙地将大语言模型的自然语言处理能力与操作系统团队的深厚经验相结合,支持自然语言问答、辅助命令执行等功能,为Linux用户带来了前所未有的智能运维与开发体验。
|
监控 安全 应用服务中间件
wordpress被恶意搜索攻击(网址/?s=****)解决方法。
综上所述,保护WordPress网站不受恶意搜索攻击涉及到多种技术和策略。从使用插件到配置服务器和CDN服务,每种方法都为网站的安全提供了一个防御层。务必定期更新维护你的网站,保持安全插件和WordPress核心的最新状态,以预防可能出现的新攻击方式。安全是一个持续的过程,对网站进行定期的安全审查和优化是至关重要的。
371 0
|
机器学习/深度学习 人工智能 自然语言处理
|
存储 资源调度 算法
m基于FPGA和IP核的RS编译码verilog实现,包含testbench测试文件
m基于FPGA和IP核的RS编译码verilog实现,包含testbench测试文件
335 1
|
安全 JavaScript Oracle
看完这篇 教你玩转渗透测试靶机Vulnhub——Momentum:1
看完这篇 教你玩转渗透测试靶机Vulnhub——Momentum:1
274 0
|
消息中间件 网络协议 安全
基于网关服务治理的研究与实践(五)从开源网关到自研网关
在上一篇API网关介绍中,由于开源网关方案的不足,且目前没有能够同时兼容Http、Socket、WebSocket协议的开源网关,无法实现对业务请求的统一管控,对于服务治理整体方案略有不足;在当前背景下,产生了自研网关的想法,本篇文章详细记录了自研网关所做的技术研究内容。
2291 0
基于网关服务治理的研究与实践(五)从开源网关到自研网关
|
JavaScript API
vue3:生命周期(onErrorCaptured)
vue3:生命周期(onErrorCaptured)
427 0