【ACM算法】-- 数学问题篇 - 最大公约数

在这里插入图片描述
在这里插入图片描述
思想:

公约数:若存在整数 c 使得 a%c=0 && b%c=0 ,则称 c 为 a 、b 的公约数,在这些公约数中选择最大的正整数 d 作为最大公约数。

  1. 关于最大公约数,对于许多读者来说,解此种类型的题可能只是存在一个固定的思路,即:
    1. 若 a 、b 均为 0 ,则其存在无数个公约数,所以最大公约数不存在。
    2. 若 a 、b 只存在一个不为零的数,则最大公约数为那个不为零的数。
    3. 若 a 、b 均不为零,则遍历 a 、b 中较小的数,因为需要明确,a 和 b 的公约数,肯定是小于 min(a,b) 的所以只需要遍历其中较小的数即可,对于每一个数,都测试是否 a%c=0 &&b%c=0 如果成立,则为公约数,这时,在来一个记录变量,记录当前最大公约数。

综上:此种简单朴素的传统方法,耗时长,运行速度缓慢。所以弃用。

  1. 欧几里得算法:
    1. 假设 x 为 a % b ,则 x 与 a(或 b)的最大公约数与 a 与 b 的最大公约数相同,具体论证不再证明。
    2. 所以 a 与 b 的最大公约数转为求 a % b 与 a(或 b)的最大公约数,如此递归下去,直到其中一个为零,则另一个不为零的值即为最大公约数。

综上:欧几里得算法简单有效,较之传统方法有很大提升。

代码如下:

#include<stdio.h>
int gcd(int a,int b){
	if(b==0) return a;
	return gcd(b,a%b);//此处涉及的交换位置是极其重要的核心,
	//格式必须为(b,a%b),就是两个值一次递归一次调换位置,
	//否则就会出错 
}

int main(){
	int a,b;
	while(scanf("%d%d",&a,&b)!=EOF){
		printf("%d\n",gcd(a,b));
	}
	return 0;
}

出错分析:
在上文提及的,位置问题,解释如下:设传入形参为 a 、b

  1. 若递归下去的是(a,a%b),这时,当 a < b 时,递归下去的为 ( a , a ) 此时就与 b 无关了,产生了错误。
  2. 若递归下去的是(a,b%a),这时,当 a > b 时,递归下去的就会恒为 ( a , b ) 此时就产生了错误。
  3. 若递归下去的是(b,b%a),这时,当 a > b 时,递归下去的为 ( b , b ) 此时就与 a 无关了,产生了错误。
  4. 若递归下去的是(b,a%b),这时,无论 a <> b,程序递归下去的都不会是某一个参数本身。程序运行成功。
  5. 若递归下去的是(b%a,a),这时,无论 a <> b,程序递归下去的都不会是某一个参数本身。程序运行成功。

综上:递归的时候,形参与实参的对应位置必须发生转换,即,对于不变的数,其必须相对于其传进来的数的位置发生改变,并且其在另一个参数,必须做分母。并且 return 判断的时候,要进行相应的判断,即分母不为零的问题

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值