C++知识点总结(7):枚举算法之最大公约数和最小公倍数

一、枚举算法

        枚举算法,将问题的所有可能的情况进行逐一列举,然后筛选出符合要求的一种程序处理算法。

        枚举算法(特别是暴力枚举的时候)的缺点是,容易超时。一个计算机一般 1 秒最多运行 1e8 次,一旦超过 1e8 组数据,就有可能超时。

        枚举三要素:

1. 枚举对象(要枚举的对象)

2. 枚举范围(每一个枚举对象从几开始,到几结束)

3. 筛选条件(筛选满足一定条件的数据)

二、最大公约数

        约数:如果一个整数 a 能被整数 b 整除,那么 b 就是 a 的约数

        公约数:两个或者多个数公有的约数

        计算两个整数 a 和 b 的最大公约数,如何利用程序实现?

1. 枚举对象:1 个数 x(可能是最大公约数的数)

2. 枚举范围:1 <= x <= min(a, b)

3. 筛选条件:如果 a % x 是 0 ,并且 b % x 也是 0

建议倒序遍历

        根据上述思路,我们写出代码:

#include <iostream>
using namespace std;

int main()
{
	// 输入两个数字 
	int a, b;
	cin >> a >> b;
	
	// 枚举算法
	int minn = min(a, b);
	for (int i = minn; i >= 1; i--)
	{
		if (a % i == 0 && b % i == 0)
		{
			cout << i;
			break;
		}
	} 
	return 0;
}

时间复杂度O(n),概念图如下:

测试结果:

 

        于是,我们还需要继续……嗯,现在教大家一种方法——辗转相除法,用了就无敌了

        将除数 b 当作下一次的被除数,余数 r 当作下一次的除数。如此反复地进行,一旦余数是 0 ,最后余数是 0 算式的除数。

比如说 63 ÷ 24。

63 ÷ 24 = 余15

24 ÷ 15 = 余9

15 ÷ 9 = 余6

9 ÷ 6 = 余3

6 ÷ 3 = 余0

所以 63 和 24 的最大公约数是 3 。

        辗转相除法程序逻辑:

int a, b, r;
while (a % b)
{
    r = a % b; // 得到余数
    a = b; // 除数作为下一次的被除数
    b = r; // 余数作为下一次的除数
}
cout << b;

        是的,这样就 OK 啦。

三、最小公倍数

1. 枚举对象:1 个数 y(可能是最小公倍数的数)

2. 枚举范围:max(a, b) <= y <= a × b

3. 筛选条件:如果 y % a 是 0 ,并且 y % b 也是 0

建议正序遍历

#include <iostream>
using namespace std;

int main()
{
	// 输入 
	int a, b;
	cin >> a >> b;
	
	// 枚举算法
	int maxn = max(a, b);
	for (int i = maxn; i <= a*b; i++)
	{
		if (i % a == 0 && i % b == 0)
		{
			cout << i;
			break;
		}
	}
	return 0;
}

        拓展一个特殊关系:

整数 a × 整数 b = 最大公约数 × 最小公倍数

#include <iostream>
using namespace std;

int main()
{
	// 输入 
	long long a, b;
	cin >> a >> b;
	long long olda = a, oldb = b;
	
	// 枚举算法
	int r;
	while (a % b)
	{
		r = a % b;
		a = b;
		b = r;
	}
	cout << olda*oldb/b;
	return 0;
} 

        这样,其实我们最小公倍数用的就是公式,大部分都是最大公约数的程序。

四、真题

题目描述

输入两个正整数x0,y0(2<=x0<100000,2<=y0<=100000),求出满足下列条件的P,Q的个数

条件:

1.P,Q是正整数

2.要求P,Q以x0为最大公约数,以y0为最小公倍数.

试求:满足条件的所有可能的两个正整数的个数.

输入描述

输入二个正整数x0,y0(2<=x0<100000,2<=y0<=100000)

输出描述

输出满足条件的P,Q的个数。

样例1

输入

3 60

输出
 

4

提示

说明(不用输出)此时的P  Q分别为:

3   60

15   12

12   15

60    3

所以:满足条件的所有可能的两个正整数的个数共4种.

解题思路

1. 枚举对象:p ( q 可以通过 x × y ÷ p 得到)

2. 枚举范围:x <= p <= y
3. 筛选条件:如果 p 和最大公约数 x 相等

参考代码

#include <iostream>
using namespace std;

int main()
{
	// 输入 
	long long x, y;
	cin >> x >> y;
	
	// 枚举算法 
	long long p, q, cnt = 0;
	for (int i = x; i <= y; i++)
	{
		p = i;
		q = x*y/p;
		if (x * y % p == 0)
		{
			// 寻找 p 和 q 的最大公约数,得到最大公约数 q 
			while (p % q)
			{
				r = p % q;
				p = q;
				q = r;
			}
			if (q == x)
			{
				cnt++;
			}
		} 
	}
	
	// 输出所有可能 
	cout << cnt;
	return 0;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值