【编程珠玑】【第二章】编程求解最大公约数和最小公倍数

一、简介

两个整数的最大公约数是能够同时整除它们的最大的正整数。辗转相除法基于如下原理:两个整数的最大公约数等于其中较小的数和两数的相除余数的最大公约数。例如,252和105的最大公约数是21(252 = 21 × 12;105 = 21 × 5),因为252 ÷105 = 2......42,所以(105,42)是21。在这个过程中,较大的数缩小了,所以继续进行同样的计算可以不断缩小这两个数直至余数变为零。这时的除数就是所求的两个数的最大公约数。

由辗转相除法也可以推出,两数的最大公约数可以用两数的整数倍相加来表示,如21 = 5 × 105 + (?2) × 252。这个重要的等式叫做贝祖等式(又称“裴蜀定理”)。

  设两数为a、b(a>b),求a和b最大公约数(a,b)的步骤如下:

  用a除以b,得a÷b=q......r1(0≤r1)。

  若r1=0,则(a,b)=b;

  若r1≠0,则计算(b,r1),用b除以r1,得b÷r1=q......r2 (0≤r2).

  若r2=0,则(a,b)==(b,r1)==r1,

  若r2≠0,则计算(r1,r2),用r1除以r2,得r1÷r2=q......r3 (0≤r3)

  ……

  如此下去,直到某个除法运算余数为0为止。这个除法运算的除数即为所求最大公约数。例如:a=25,b=15,a/b=1......10, b/10=1......5, 10/5=2.......0, 最后一个除法的除数为5,就是所求最大公约数(25, 15)。

代码一:

#include <stdio.h>
unsigned gcd_rec( unsigned m,unsigned n ){
    unsigned temp;
    if (m<n){         //m保存较大值,n保存较小值,不满足则交换二者的值
        temp=m;m=n;n=temp;
    }
    if ( m%n == 0){  //如果余数为0则意味着n为m,n的最大公约数
        return n;
    }else{           //否则需要使用较小的数n和两数的相除余数m%n继续求解
        return gcd(n,m%n) ;
    }
}
int main( void ){
    unsigned m,n;
    printf("请输入两个正整数:");
    scanf("%u%u",&m,&n);
    printf("%u与%u的最大公约数为:%u\n",m,n,gcd ( m,n ) );
    return 0;
}

代码二:当然也可以不使用递归,使用迭代的方法进行计算,代码如下:

#include <stdio.h>
void gcd_iter(unsigned m,unsigned n ){
  int r;
  while(n!=0){
      r=m%n;
      m=n;
      n=r;
  }
  printf("%d\n",u);}

从这个代码中可以看出实际上并不必须使用u和v中的较小值进行下一次迭代除法,不过为尽快缩小计算规模选择较小的值更有好处。这里没有比较二者的值并选择其中较小值,不影响计算结果的正确性,而且代码更清晰,但是性能上有一些影响。

代码三:辗转相减求最大公约数

思想:最大公约数能整除i和j,则其一定也能整除i-j(if i>j)

void gcd(int m, int n){
    while(m != n) {
        if(m > n)
            m -= n;
        else
            n -= m;
    }
    printf("%d\n",m);
}

二、原理的证明

设两数为a、b(b<a),用gcd(a,b)表示a,b的最大公约数,r=a (mod b) 为a除以b以后的余数,k为a除以b的商,即a÷b=k.......r。辗转相除法即是要证明gcd(a,b)=gcd(b,r)。

  第一步:令c=gcd(a,b),则设a=mc,b=nc(此时m与n互质)。

  第二步:根据前提可知r =a-kb=mc-knc=(m-kn)c

  第三步:根据第二步结果可知c也是r的因数

  第四步:可以断定m-kn与n互质【假设他们不互质,二者存在非1的公约数d,使得m-kn = xd, n = yd。那么,m = xd + kyd = (x + ky)d,那么,a = mc = (x + ky)dc , b = nc = ydc,=> a,b的最大公约数为dc,而不是c,这与前面结论矛盾】

  第五步:既然m - kn与n互质,且已知b=nc,r =(m-kn)c,则能得出b和r的最大公约数为c,即为c = gcd(r,b),又令c=gcd(a,b)进而gcd(a,b)=gcd(b,r)。

  证毕。

三、最小公倍数

最小公倍数:数论中的一种概念,两个整数公有的倍数成为他们的公倍数,其中一个最小的公倍数是他们的最小公倍数。

最小公倍数=两整数的乘积÷两整数最大公约数:a * b / gcb(a,b)

原文地址:https://www.cnblogs.com/blastbao/p/8306730.html

时间: 2024-10-10 08:28:56

【编程珠玑】【第二章】编程求解最大公约数和最小公倍数的相关文章

一维向量旋转算法 编程珠玑 第二章

看了编程珠玑第二章,这里面讲了三道题目,这里说一下第二题,一维向量旋转算法. 题目:将一个n元一维向量(例数组)向左旋转i个位置. 解决方法:书上讲解了5种方法,自己只想起来2种最简单方法(下面讲的前两种). 1.原始方法. 从左向右依次移动一位,对所有数据平移:这样循环i次,算法最坏时间复杂度达n^2.耗时不推荐. 2.空间换时间. 顾名思义,申请一个i长度的空间,把前i半部分放到申请空间中,再把后面的所有数据向左移动i个位置,最后把申请的空间中的数据放到后半部分.浪费空间,不推荐. 3.杂技

编程珠玑第二章

编程珠玑第二章 A题 给定一个最多包含40亿个随机排列的32位整数的顺序文件,找出一个不在文件中一32位整数. 1.在文件中至少存在这样一个数? 2.如果有足够的内存,如何处理? 3.如果内存不足,仅可以用文件来进行处理,如何处理? 答案: 1.32位整数,包括-2146473648~~2146473647,约42亿个整数,而文件中只有40亿个,必然有整数少了. 2.如果采用位数思想来存放,则32位整数最多需要占用43亿个位.约512MB的内存空间. 可以采用前一章的位处理方法.然后判断每个in

集体智慧编程_第二章(提供推荐)_1

前言:最近正在拜读Toby Segaran先生写的集体智慧编程,首先感谢Toby Segaran先生将知识以书本的方式传播给大家,同时也感谢莫映和王开福先生对此书的翻译,谢谢各位的不辞辛苦.首先在写随笔之前,跟各位分享一下我的编程环境:win7系统,python版本是2.7.10,开发环境我选择的是pycharm程序.本书的第一章为集体智慧导言,主要介绍的何为集体智慧和机器学习的相关概念和其局限性,以及与机器学习相关的例子和应用场景.下面开始机器学习第二章--提供推荐的相关内容. 本章主要内容:

数据结构与算法分析C++表述第二章编程题

把昨天看的第二章巩固一下,做一做编程习题. 2.6: 第一天交2元罚金,以后每一天都是前一天的平方,第N天罚金将是多少? 这个题目和2.4.4-3介绍的幂运算基本一致.若按相同的递归思路分析,比那个问题要简单,因为从1次幂开始并且指数呈2^(n-1)分布,即1,2,3,4,16……所以没有对指数是奇数时的判定.实际上用循环来求要比用递归快.在不考虑溢出的前提下,解法如下: #include<iostream> using namespace std; typedef unsigned long

java编程思想 第二章

这篇时间较之前篇章时间靠后,是由于,某一天晚上看完Java编程思想文献之后来不及做笔记了. 以下笔记基本为转载,不是原创 第二章   一切都是对象 目录: 2.1 用引用操纵对象 2.2 必须由你创建所有对象 2.3 永远不需要销毁对象 2.4 创建新的数据类型:类 2.5 方法.参数和返回值 2.6 构建一个Java程序 2.7 你的第一个Java程序 2.8 注释和嵌入式文档 2.9 编码风格 2.1 用引用操纵对象 一切都看作对象,操纵的标识符实际上是对象的一个“引用”,遥控器(引用)操纵

[书籍翻译] 《JavaScript并发编程》 第二章 JavaScript运行模型

本文是我翻译<JavaScript Concurrency>书籍的第二章 JavaScript运行模型,该书主要以Promises.Generator.Web workers等技术来讲解JavaScript并发编程方面的实践. 完整书籍翻译地址:https://github.com/yzsunlei/javascript_concurrency_translation .由于能力有限,肯定存在翻译不清楚甚至翻译错误的地方,欢迎朋友们提issue指出,感谢. 本书第一章我们探讨了JavaScri

【编程小题目5】求解最大公约数和最大公倍数

题目:输入两个正整数m和n,求其最大公约数和最小公倍数. 程序分析:利用辗除法求最大公约数:最大公倍数等于m * n / Gcd(m,n). #include <iostream> using namespace std; int main() { int n, m; int k,r = 1; cout << "Plese input the number n and m:"; cin >> n >> m; k = n * m; whil

对一千万条数据进行排序---编程珠玑第二版 第一章

本书第一章提出了一个看似简单的问题,有最多1000万条不同的整型数据存在于硬盘的文件中,如何在1M内存的情况下对其进行尽可能快的排序. 每个数字用4byte,1M即可存储250 000个数据,显然,只要每次对250 000个数据排序,写入到文件中即可,重复40次. 那么如何选出每次遍历的二十五万条数据呢?有如下两个策略: 1.对一千万条数据遍历40次,第i次遍历时,判断数是否属于[i*250000,i*250000+249999),如果是,则读入内存,当第i次遍历完成时,内 存中有了二十五万条数

Python核心编程_第二章课后习题

以下是自己在学习Python核心编程时,做的课后练习题.现在把它们贴出来,以记录自己的学习过程.小弟是机械出身,很多练习题目写的很是机械.虽然写出来的脚本都能满足题目要求,但效率可能不是最好的,所以,小弟还是厚着脸皮把它们给贴出来,一来可以让高手指点,二来可以与我一样在学习Python的兄弟共同学习. 以下的程序均以题目标号命名,如2-3这个题目,程序名就为2_3.py. 习题2_3.py #!/usr/bin/env python A = 10 B = 4 print "A plus B is