[HOJ 10178] 最大公约数 (Greatest Common Divisor)

最大公约数
Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:32768KB
Total submit users: 2211, Accepted users: 1898
Problem 10178 : No special judgement
Problem description
输入两个整数a,b(1≤a,b≤100000000),请编写程序求出他们的最大公约数。
 
Input
第一个数n表示测试数据的个数,接下来的n行每行有两个整数a b,用空格隔开
 
Output
输出n行,每行输出对应a,b的最大公约数
 
Sample Input
3
12 8
25 10
21 63
Sample Output
4
5
21
Problem Source
CSU 1st Contest

解法1:暴力,超时

算法:最容易想到的暴力法,从 a,b  两个数中的较小数开始向下逐步试探能否同时整除两个数,可以就得到答案,时间复杂度 O(max(a, b)) 结果超时。

[HOJ 10178] 最大公约数 (Greatest Common Divisor)

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>   
#include <vector>

int min(int a, int b) { return a < b ? a : b; }

int main()
{
    int n, a, b, s, m;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
    {
        scanf("%d %d", &a, &b);
        s = 1, m = min(a, b);
        for (int i = m; i >= 1; --i)
        {
            if (a % i == 0 && b % i == 0) {
                s = i; break;
            }
        }
        printf("%d\n", s);
    }
    return 0;
}

解法2:辗转相除法

[HOJ 10178] 最大公约数 (Greatest Common Divisor)

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>  

int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }

int main()
{
    int n, a, b, big, small, f=0;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
    {
        scanf("%d %d", &a, &b);
        big = max(a, b);
        small = min(a, b);
        while (small)
        {
            f = small;
            a == big ? a %= small : b %= small;
            big = max(a, b);
            small = min(a, b);
        }
        printf("%d\n", f);
    }
    return 0;
}

解法3:更相减损术

算法:可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。 —— 《九章算术》

该算法原本是为约分而设计的,就是用来给分子分母同时约分,约到最简分数,也可以用来求任意两个数的最大公约数。

翻译:

第一步:有两个数 a,b 现在要将其约到最简,如果 a, b 可以整除 2 就都约去 2,如果 a, b  均和 2 互质,执行第二步

第二步:分子分母两数做差,大的减掉小的,如果减完分子分母不相等,重复第二步,否则进入第三步

第三步:使用第二步中相减为零的两个被减数和减数,用其中一个对原来的分子分母进行约分,算法结束

图示:以题目数据 21 63 为例

[HOJ 10178] 最大公约数 (Greatest Common Divisor)

 AC:

[HOJ 10178] 最大公约数 (Greatest Common Divisor)

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>  

int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }

int main()
{
    int n, a, b, big, small, f;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
    {
        scanf("%d %d", &a, &b);
        f = 1;
        while (!(a & 1) && !(b & 1)) a >>= 1, b >>= 1, f <<= 1;
        big = max(a, b);
        small = min(a, b);
        while (big != small)
        {
            a == big ? a -= b : b -= a;
            big = max(a, b);
            small = min(a, b);
        }
        printf("%d\n", small * f);
    }
    return 0;
}

[HOJ 10178] 最大公约数 (Greatest Common Divisor)

 

 

 

 

上一篇:条款31.避免默认捕获模式


下一篇:LeetCode知识点总结 - 231