系列文章目录
● 算法笔记01|欧几里得GCD算法(附C++代码)
● 算法笔记02|洗牌算法(附C++代码)
前言
最大公约数(GCD,Greatest Common Divisor)问题,即求两个或多个整数共有约数中最大的一个。
- 求取两个数GCD的直观方法——整数的因子分解法
即将每个整数分解为素因子的积,找出公共的素因子,他们的积即是GCD。
例如:210=2x3x5x7; 252=2x2x3x3x7; 公共素因子为2x3x7=42,所以210和252的GCD为42。
本文所讲的Euclid GCD算法被誉为人类史上第一个算法,是极少从古至今都有着重要应用的算法,奠定当前网络安全的著名RSA算法就用到了Euclid GCD算法。
一、欧几里得GCD定理
这里需提前知道欧几里得的另一个重要贡献,即高效率求取 GCD 的 Euclid GCD定理,它包括如下两条:
- gcd (a, 0) = a
- gcd (a, b) = gcd (b, a MOD b)
其中 MOD 运算为求模 即通常所说的求余数运算
二、欧几里得GCD算法
1. 算法思想
Euclid GCD算法的主要思想是通过不断利用较小的数对较大的数求余运算,逐渐减小数字大小,最终使其中一个数变为0,那么另一个数即为GCD。下面给出一个示例:
2. 算法伪代码
//初始条件:初始条件:给定整数 𝒂≥𝟎,𝒃≥𝟎,且 𝒂,𝒃不同时为 0;
//目标:求 𝒂,𝒃的最大公约数。
//方法:
1. 输入a,b
2. while b ≠ 0
3. r = a MOD b
4. a = b
5. b = r
6. 转2
7. 输出结果:a
3. 算法复杂度
算法复杂度:O(logalogb)
其中对数是以2为底的对数。
4. 算法代码(c++)
include <stdio.h>
namespace NS_EuclidGCD {
int EuclidGCD(int a, int b)
{
int r;
while (b) {
r = a % b;
a = b;
b = r;
}
return a;
}
}//namespace NS_EuclidGCD
using namespace NS_EuclidGCD;
void TestEuclidGCD()
{
#define N 22
int ab[N][2] = {
//Wikipedia
{ 252, 105 },
//Introduction to Algorithms
{ 30, 21 },
{ 99, 78 },
//https://www.calculatorsoup.com/
{ 816, 2260 },
//Algorithms, S. Dasgupta
{ 1035, 759 },
//http://everything.explained.today
{ 1386, 3213 },
//https://www.cs.cornell.edu
//Example of Extended Euclidean Algorithm
{ 84, 33 },
{ 432, 95256 },
//https://www.rit.edu,
//The Euclidean Algorithm
{ 12, 18 },
{ 24, 54 },
{ 168, 180 },
{ 244, 354 },
{ 128, 423 },
{ 406, 555 },
{ 220, 1323 },
{ 3846, 153 },
{ 1424, 3084 },
{ 2415, 3289 },
{ 4278, 8602 },
//Other
{ 72, 84 },
{ 102, 138 },
{ 26187, 1533 }
};
for (int i = 0; i < N; i++) {
int a = ab[i][0];
int b = ab[i][1];
int gcd = EuclidGCD(a, b);
printf("The GCD of %d and %d is %d\n",
a, b, gcd);
}
}
三、写在后面
文本是对内容是对山东师范大学徐老师的课件内容整理归纳及补充,仅供自己复习参考,如有侵权立即删除。