每日一题(75) - 最大公约数问题
来源:互联网 发布:各大编程语言效率比较 编辑:程序博客网 时间:2024/05/01 11:48
题目来自编程之美
题目
注意:这里不考虑负数。
思路(1)辗转相除法
思想:
参数要求:无要求,x >= y 或 y >= x均可gcd(x,y) = gcd(y ,x % y);原理:
假设 x = ky + b,其中 k = x/y,b = x%y.
则,b = x - ky
假设 整数t同时整除x和y,则
式子两边同时除以t,得
b / t = (x - ky) / t = 整数
则,b = x%y 也能整除t。
即,x 和 y的最大公约数 等于 y和 x%y 的最大公约数。
注意,这里我们只考虑正数,即有x > y。
此时,就有了 gcd(x,y) = gcd(y ,x % y),y > 0;
在式子中,右边的参数参数都在减小,即把原问题转换为求两个更小数的公约数了,一直到其中一个数为0,则另外一个数就为其最大公约数。
举例:
30 和 12 的最大公约数 等于 12 和 6 的最大公约数。
12 和 6 的最大公约数 等于 6 和 0 的最大公约数。
6 和 0 的最大公约数 等于 6,则30 和 12 的最大公约数 等于 6。
特点:计算次数比较少,但是取模运算运算代价昂贵,尤其是针对大数据。
代码:
int Gcd(int x,int y){return y == 0 ? x : Gcd(y,x % y);}代码注意事项:
(1)传参时,不需要要求x > y。
(2)需要注意程序的形参(x,y)和入口参数的顺序(y,x%y)。
思路(2)两数相减法
思想:
参数要求:有要求,x >= ygcd(x,y) = gcd(y,x - y);举例:
<1> 30 和 12 的最大公约数 等于 12 和 18 的最大公约数。
<2> 18 和 12 的最大公约数 等于 12 和 6 的最大公约数。
<3> 12 和6 的最大公约数 等于 6 和 0 的最大公约数。
<4> 6 和 0 的最大公约数 等于 6,则30 和 12 的最大公约数 等于 6。
特点:计算次数比较多,但是不需要取模运算。
代码:
int Gcd(int x,int y){if (y > x){return Gcd(y,x);/*要求x > y*/}return y == 0 ? x : Gcd(y, x - y);}
代码注意事项:
(1)传参时,要求x > y。
(2)在程序执行过程中,也有可能出现 x < y 的情况(如举例中第一次计算就出现了),因此需要在程序中写交换语句。
思路(3)辗转相除法与相减结合
引入的原因:结合两种方法,使得迭代次数少 且 又没有取模等代价昂贵的运算,继而快速求解大数据的最大公约数。
思路:
运用取模运算的性质:
对于 x 和 y 来说,
(1)如果x = k * x1 且 y = k * y1,则x 和 y的最大公约数等于 k * (x1 和 y1的最大公约数)。
(2)如果x = p * x1 且 p 素数 且 y % p != 0,则x 和 y的最大公约数等于x1 和 y的最大公约数。
在程序中,需要寻找一个类似(2)的p,即需要判断p是否是x或者y的因子。
由于在程序中判断2是否是一个数的因子还是比较方便的,这里就令p = 2。
为啥是方便的呢?
判断2是否为x的因子,即判断x是否为偶数。可以直接使用位运算,来判断x是否为偶数,很方便。
这样,我们可以通过除2来减少计算次数。
具体思路:
如果 x为偶,y为偶,则gcd(x,y) =2 * gcd(x >> 1,y >> 1)。
如果 x为偶,y为奇,则gcd(x,y) = gcd(x >> 1,y)。
如果 x为奇,x为偶,则gcd(x,y) = gcd(x,y >> 1)。
如果 x为奇,x为奇,则gcd(x,y) = gcd(y,x - y)。
在执行gcd(y,x - y)后,这俩参数一个为奇数,一个为偶数,下一步就又有除2操作了。
注意:当x和y均为偶数时,别忘了乘以2。
分析:
为啥呢:如果x为2的幂且y = 3,则可以一直除2,一直到最后。
举例:
<1> 30 和 12 的最大公约数 等于 15 和 6 的最大公约数 * 2。
<2> 15 和 6 的最大公约数 等于 15 和 3 的最大公约数。
<3> 15 和 3 的最大公约数 等于 3 和 12 的最大公约数。
<4> 12 和 3 的最大公约数 等于 6 和 3 的最大公约数。
<5> 6 和 3 的最大公约数 等于 3 和 3 的最大公约数。
<6> 3 和 3 的最大公约数 等于 3 和 0 的最大公约数。
<7> 3 和 0 的最大公约数 等于 3,则30 和 12 的最大公约数 等于 6。
注意:别忘了乘以2.
代码:
int Gcd(int x,int y){if (x < y){return Gcd(y,x);/*形参要求 x > y */}if (y == 0){return x;}if ((x & 1) == 0) //x为偶数{if ((y & 1) == 0) //x为偶数,y为偶数{return Gcd(x >> 1,y >> 1) << 1;//别忘了乘以2}else //x为偶数,y为奇数{return Gcd(x >> 1,y);}}else{if ((y & 1) == 0) //x为奇数,y为偶数{return Gcd(x,y >> 1);}else //x为奇数,y为奇数{return Gcd(y,x - y);}}}
代码注意事项:
(1)传参时,要求x > y。
(2)在程序执行过程中,也有可能出现 x < y 的情况,因此需要在程序中写交换语句。
- 每日一题(75) - 最大公约数问题
- 每日一题(75) - 最大公约数问题
- 每日一题 No.8 求最大公约数
- [每日练习]最大公约数问题
- 每日一题:过桥问题
- 每日一练------最小公倍数、最大公约数求解
- [每日练习]最大公约数问题的推倒
- 每日一题系列 - 荷兰国旗问题
- 【每日一题】字符串是否包含问题
- 每日一题 隐式图 倒水问题
- 每日一题17:八皇后问题
- 链表带环问题【每日一题】
- 链表相交问题【每日一题】
- Nswoj每日一题:括号配对问题
- 【每日一题】2012.6.29:全排列问题(非原创)
- 每日一题(1)——滑雪问题(动态规划)
- 每日一题(73) - 字符串移位包含的问题
- 每日一题(1)——滑雪问题(动态规划)
- UVALive 3530 Martian Mining
- 经济学原理---2 像经济学家一样思考 --- 读书笔记
- iOS 学习资源
- Esper学习之二:事件类型
- php真的难么难学吗
- 每日一题(75) - 最大公约数问题
- 【Lucene3.6.2入门系列】第01节_HelloWord
- flash builder 4.7 下载、破解
- MessageBox
- Opencv 文本输入
- zoj 2016 Play on Words 欧拉回路
- dynatrace 前端性能测试分析案例
- 给自己的备忘录——面向对象
- java数据类型