思想:
公约数:若存在整数 c 使得 a%c=0 && b%c=0 ,则称 c 为 a 、b 的公约数,在这些公约数中选择最大的正整数 d 作为最大公约数。
- 关于最大公约数,对于许多读者来说,解此种类型的题可能只是存在一个固定的思路,即:
- 若 a 、b 均为 0 ,则其存在无数个公约数,所以最大公约数不存在。
- 若 a 、b 只存在一个不为零的数,则最大公约数为那个不为零的数。
- 若 a 、b 均不为零,则遍历 a 、b 中较小的数,因为需要明确,a 和 b 的公约数,肯定是小于 min(a,b) 的所以只需要遍历其中较小的数即可,对于每一个数,都测试是否 a%c=0 &&b%c=0 如果成立,则为公约数,这时,在来一个记录变量,记录当前最大公约数。
综上:此种简单朴素的传统方法,耗时长,运行速度缓慢。所以弃用。
- 欧几里得算法:
- 假设 x 为 a % b ,则 x 与 a(或 b)的最大公约数与 a 与 b 的最大公约数相同,具体论证不再证明。
- 所以 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
- 若递归下去的是(a,a%b),这时,当 a < b 时,递归下去的为 ( a , a ) 此时就与 b 无关了,产生了错误。
- 若递归下去的是(a,b%a),这时,当 a > b 时,递归下去的就会恒为 ( a , b ) 此时就产生了错误。
- 若递归下去的是(b,b%a),这时,当 a > b 时,递归下去的为 ( b , b ) 此时就与 a 无关了,产生了错误。
- 若递归下去的是(b,a%b),这时,无论 a <> b,程序递归下去的都不会是某一个参数本身。程序运行成功。
- 若递归下去的是(b%a,a),这时,无论 a <> b,程序递归下去的都不会是某一个参数本身。程序运行成功。
综上:递归的时候,形参与实参的对应位置必须发生转换,即,对于不变的数,其必须相对于其传进来的数的位置发生改变,并且其在另一个参数,必须做分母。并且 return 判断的时候,要进行相应的判断,即分母不为零的问题