题目描述
求整数a、b的最大公约数。
题目分析
所谓求整数a、b的最大公约数,就是求同时满足a%c=0、b%c=0的最大正整数c,即求能够同时整除a和b的最大正整数c。
暴力枚举
若a、b均不为0,则依次遍历不大于a(或b)的所有正整数,依次试验它是否同时满足两式,并在所有满足两式的正整数中挑选最大的那个即为所求;
若a、b其中有一个为0,那么最大公约数即为a、b中非零的那个;
若a、b均为0,则最大公约数不存在(任意数均可同时整除它们)。
说明:当a和b数值较大时(如100000000),该算法耗时较多。
欧几里德算法(又称辗转相除法)
若a、b全为0,则它们的最大公约数不存在;若a、b其中之一为0,则它们的最大公约数为非0的那个;若a、b都不为0,则使新a=b;新b=a%b然后重复该过程。
说明:证明过程见最下边。
代码实现
递归实现
#include <iostream> using namespace std; int gcd(int a, int b) { if (a == 0 && b == 0) return -1; // 不存在 // a、b为负数时,先求绝对值,再求最大公约数 if (a < 0) a = -a; if (b < 0) b = -b; if (b == 0) return a; return gcd(b, a%b); } int main() { int m, n; while (cin >> m >> n) { cout << gcd(m, n) << endl; } return 0; }
循环实现
#include <iostream> using namespace std; int gcd(int a, int b) { if (a == 0 && b == 0) return -1; // 不存在 // a、b为负数时,先求绝对值,再求最大公约数 if (a < 0) a = -a; if (b < 0) b = -b; while (b != 0) { int t = a%b; a = b; b = t; } return a; } int main() { int m, n; while (cin >> m >> n) { cout << gcd(m, n) << endl; } return 0; }
欧几里德算法证明
1> 证明a、b的公约数同时也是b、a mod b 的公约数
2> 证明若g是a、b的最大公约数,它同样也是b、a mod b 的最大公约数
我们假设g是a、b的最大公约数,但它并不是b、a mod b 的最大公约数,