/**
* 本程序用于求解两个正整数的最大公约数
* 求解最大公约数往往可以用的有三种方法:
* eg: 求正整数x和y的公约数
* 1. 遍历, 从1遍历到min(x, y)为止, 找到能够同时被两数整除的最大整数
* 2. 辗转相除法, 取k = x/y, b = x % y, 则 x = k * y + b; 如果一个数能同时整除x和y, 则其一定能同时整除b和y, 即x和y的公约数与b和y的公约数是相同的, 其最大公约数也相同. 所以f(x, y) = f(y, x % y) (x >= y > 0)
* 辗转相除法证明:
* If x和y, 其最大公约数为d, 则 x = k1 * d, y = k2 * d; 令k = x / y, b = x % y, 则x = k * y + b. 代入, 则k1 * d = k * k2 * d + b, 等号左右相等, 且等式中所有的字符均代表一个整数, 因此等式左右两侧均能被d整除.
* 等号右侧中, k * k2 * d本身可以被d整除, 因此b也一定能被d整除, 因此d也一定是b和y的公因数.
* 现在证明d是b和y的最大公因数.
* 假设b和y存在更大的公因数D > d,
* 则在等式x = k * y + b中, b / D和k * y / D的结果均为整数, 因此x / D也为整数, 即x / D = k * y / D + b / D. 则此时x和y均能被D整除, 因此D为x和y的公因数, 又因d为x和y的最大公因数, 而假设D > d, 互相矛盾了, 所以假设不成立
* 即, b和y不存在更大的公因数, 即b和y的最大公因数也是d.
*/
#include<stdio.h>

int Division(int x, int y) {
if (!y)
return x;
else
return Division(y, x % y);
}

/**
* 3. 相减法. 如果一个数能同时整除x和y, 则其一定能同时整除x - y和y(x > y), 即f(x, y) = f(x - y, y).
* 与辗转相除法相比, 相减法可以用减法运算代替求模运算, 相对开销要小一些, 但是程序迭代的次数却多了很多, 尤其是在f(10000, 1)这种类型的运算时.
* 相减法证明:
* 与辗转相除法相同, f(x, y) = d, x = k1 * d, y = k2 * d, x = k * y + b.
* 则: x - y = k * y - y + b, 两边同时除以d, 得到, k1 - k2 = (k - 1) * k2 + b / d, 上文中已经证明b可以被d整除因此等式成立, 且左右均为整数, 因此x - y可以被d整除.
* 与上文同样方法可以证明d为x - y和y的最大公约数.
*/
int Minus(int x, int y) {
if (x < y) {
x = x ^ y;
y = x ^ y;
x = x ^ y;
}
if (y == 0)
return x;
return Minus(x - y, y);
}

/**
* 4. 改进算法, 结合辗转相除法和相减法
* 此算法的主要依据为两个公式:f(x, y) = f(k * x1, k * y1) = k * f(x1, y1), f(x, y) = f(p * x1, y) = f(x1, y)(p是素数且y不能被p整除)
* 对于x和y, 如果x = k * x1, y = k * y1, 则f(x, y) = f(k * x1, k * y1) = k * f(x1, y1).
* 证明:
* 假设d = f(x, y), 即d为x和y的最大公约数. 因此x = d * x2, y = d * y2.
* 假设k不能整除d, 则如下所示:
* d * x2 = k * x1, d * y2 = k * y1. 等号两边同时除以k, 由于d不能被k整除, 则x2和y2必然能被k整除, 因此x2和y2必然存在公因子k, 因此d不为x和y的最大公因数, 与假设不相符所以k能整除d.
* 等式两边同时提取k, 得到d1 * x2 = x1, d1 * y2 = y1, d1 = f(x1, y1), 且d = d1 * k. 等式成立.
* 对于第二个公式f(x, y) = f(p * x1, y) = f(x1, y)(p是素数且y不能被p整除)
* 证明:
* 令 x = p * x1(p是素数且y不能被p整除), d = f(x, y)
* 因为y不能被p整除, 所以p不能整除d(如果p能整除d, 则y必然能整除p), 又p为素数, 则d不能整除p, 因此d和p是x的两个独立的因数, 即p和d的最大公因数为1,
* 所以x = p * x1 = p * d * x2, 即x1能被d整除.
* x1 < x且为x的因子, 所以d同时为x1和y的公因子(同样可用反证法来证明一下)
*/
/**
* 将改进算法用于求解最大公因子, 由于需要做除法运算, 而在计算机的表达中, 对2做除法运算可通过右移一位来轻松实现, 因此p可以取2.
* 因此对于x和y, 求最大公约数f(x, y), 便可优化为:
* x, y均为偶数, return 2 * f(x >> 1, y >> 1)
* x, y均为奇数, f(y, x - y)
* x为奇数, y为偶数, f(x, y >> 1)
* x为偶数, y为奇数, f(x >> 1, y)
*/
/**
* 此外对于判断x和y是否为偶数的方法, 如果除法运算的话, 改进就没有意义了, 因此可以通过与运算来实现
* 对于二进制表示中,偶数的最低位为0, 奇数为1, 可通过这一特性来判断是否为偶数, 一个&运算即可.
*/

// 判断x是否为偶数. 偶数返回1, 奇数返回0
int IsEven(int x) {
return (x & 1) ? 0 : 1;
}

int Improve(int x, int y) {
if (x < y)
return Improve(y, x);
if (y == 0)
return x;
if (IsEven(x)) {
if (IsEven(y))
return 2 * Improve(x >> 1, y >> 1);
else
return Improve(x >> 1, y);
} else {
if (IsEven(y))
return Improve(x, y >> 1);
else
return Improve(x - y, y);
}
}
int main() {
int x, y;
scanf("%d%d", &x, &y);
printf("%d和%d的最大公因数为%d\n", x, y, Division(x, y));
printf("%d和%d的最大公因数为%d\n", x, y, Minus(x, y));
printf("%d和%d的最大公因数为%d\n", x, y, Improve(x, y));
return 0;
}

转载于:https://www.cnblogs.com/KingOfAlex/p/9144450.html

编程之美——2.7 求最大公约数相关推荐

  1. 编程之美 2.14求数组的子数组之和的最大值

    对于一个有N个元素的数组,a[0]~a[n-1],求子数组最大值. 如:数组A[] = [−2, 1, −3, 4, −1, 2, 1, −5, 4],则连续的子序列[4,−1,2,1]有最大的和6. ...

  2. 编程之美 2.1 求二进制中1的个数

    问题描述: 对于1个字节(8bit)无符号整型变量,求其二进制表示中"1"的个数 解法一:除2取余 (对于二进制操作,除以一个2,原来的数字会减少一个0.如果除的过程中有余数,就表 ...

  3. php怎么求最小公倍数,PHP编程求最大公约数与最小公倍数的方法示例

    本文实例讲述了PHP编程求最大公约数与最小公倍数的方法.分享给大家供大家参考,具体如下: //求最大公约数 function max_divisor($a,$b) { $n = min($a, $b) ...

  4. 《编程之美》学而思 - 最大公约数问题

    <编程之美>学而思 - 最大公约数问题 flyfish greatest common divisor 最大公约数 Euclidean algorithm, or Euclid's alg ...

  5. 从 “求最大公约数” 窥视数学,编程和算法

    算法,讲究一个巧字: 最近一直在研究算法的内容,但是我发现了一个问题,那就是在学习的时候会有一种迷茫的感觉,有时候会分不清编程和算法的关系,有时候会分不清算法和数学的关系,在这里贴出一些我的小感悟,希 ...

  6. 最小公倍数 php,PHP编程求最大公约数与最小公倍数的方法示例

    本文实例讲述了PHP编程求最大公约数与最小公倍数的方法.分享给大家供大家参考,具体如下: //求最大公约数 function max_divisor($a,$b) { $n = min($a, $b) ...

  7. 计算机编程求最大公约数与最小公倍数,这是一个常见的简单算法

    计算最大公约数和最小公倍数是简单常见的算法,他有多种方式实现,比如:穷举法.辗转相除法.相减法等等,方法很多,目的相同,下面就用其中一种方法,辗转相除法来完成这个算法,下面将用计算机编程的方式实现. ...

  8. 编程之美 求数组中的最长递增子序列

    如题,例如:存在数组 1,-1,2,-3,4,-5,6,-7 ,则最长的递增子序列是:1,2,4,6. 法一: 蛮力法 int Lis(int* arr,int n) {int iCount=0;// ...

  9. python编程练习:求最大公约数和最小公倍数

    # coding:utf-8 """ 求最大公约数和最小公倍数 两个数的最大公约数是两个数的公因子中最大的那个数: 两个数的最小公倍数是能够同时被两个数整除的那个数. & ...

最新文章

  1. Go语言源码分析CAS的实现和Java如出一辙
  2. python交互界面的退出
  3. 不用代理实现弹出进度条窗体
  4. java 1kb_[代码全屏查看]-java输入输出流及文件操作
  5. 【杂文】企业数字化转型展望—角色转型
  6. 配置php.ini文件,关闭错误提示,打开错误日志,设置错误日志路径(亲测)
  7. windows安装64位Pygame方法
  8. 设计师必备的html工具
  9. 工作167:eachrt解决问题方法思路
  10. 论文浅尝 - IJCAI2020 | Mucko:基于事实的多层跨模态知识推理视觉问答
  11. 井通swtc能不能涨到2元_买一支2块到3块之间的股票,买几十万股吗?这样操作效果怎么样?...
  12. 年度总结 | Flink 年度最佳学习路线总结
  13. python虚拟环境中安装diango_python项目部署之 django虚拟环境
  14. python大数据毕设选题
  15. xshell安装教程
  16. python的多行注释
  17. h5聊天页面 jquery_h5聊天室web端(仿微博、微信)|h5仿微信网页端|仿微信界面弹窗...
  18. 人工智能ai的有关专业术语_您需要知道的11个人工智能术语
  19. 信息学奥赛知识点(一)—计算机基础知识【转载】
  20. 彩色图像和灰度图像之间的转换

热门文章

  1. Android实现下拉头部缩放功能
  2. c# redis hashid如何设置过期时间_Redis数据库实现原理(划重点)
  3. java引用类型和值类型_[Java教程]JavaScript中值类型和引用类型的区别
  4. Python基础数据之列表知识(二)
  5. 软考计算之运筹学-决策分析问题
  6. 基于Java的RDMA高性能通信库(二):Java Socket Over RDMA
  7. mysql的默认sid_默认实例(SID)已经设置,空实例默认连接时却连接不上?
  8. 埃洛等级分系统【转自百度百科】
  9. Java程序设计第三次作业
  10. PTA L2-002 链表去重