CodeVS 天梯 1012 最大公约数和最小公倍数问题

题目链接

题目描述 Description

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

条件:  1.P,Q是正整数

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

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

输入描述 Input Description

二个正整数x0,y0

输出描述 Output Description

满足条件的所有可能的两个正整数的个数

样例输入 Sample Input

3 60

样例输出 Sample Output

4

 

以输入3  60为例

看道题目,我最开始的思路是:根据结论,两个自然数的最大公约数与它们的最小公倍数的乘积等于这两个数的乘积

1. 先得到两数之积,再分解之:180 = 2x2x3x3x5,因子用数组来保存。

2. 再排列组合得到两个数,判断他们是否满足两数最大公约数值为3的条件,但是组合起来好像有点麻烦,在网上看到黑桐的算法

 

他的算法是:

1.得到所有是3的倍数,是60的约数的集合。num[ ] = {3,6,12,15,30,60}

2.用num[]构造二维矩阵来匹配,看所对应组合是否满足(最大公约数为3 && 最小公倍数为60),但是这样一来复杂度就是O(N2了。

 

受到启发,将他的算法进行了改进,得到算法复杂度为O(N)的下面算法:

#include <iostream>
using namespace std;
bool isGcd(int a, int b, int num);
int main(){
    //int x = 3, y = 60;
    int x, y;
    cin >> x >> y;
    int count = 0;
    for (int i = x; i <= y; i += x)
    {
        if (y%i == 0){
            int a = i;//a值依此为 3,6,12,15,30,60
            int b = x*y / i;//根据性质:两个自然数的最大公约数与它们的最小公倍数的乘积等于这两个数的乘积。 b值依此为:60 30 15 12 6 3
            if (isGcd(a, b, x)){//为两数之和为已知180,如果其最大公约为3,那么其最小公倍数一定为60
                count++;
                //cout << a<<" "<< b << " * "; 
                //输出:3 60 * 12 15 * 15 12 * 60 3 *
            };
        }
    }
    cout << count;
    return 0;

}
bool isGcd(int min, int max, int num)//判断num是否为min、max两数的最大公约数
{
    int temp;
    if (min < max){
        swap(min, max);
    }
    while (max != 0){
        temp = min % max;
        min = max;
        max = temp;
    }
    return num == max ? true : false;
}
原文地址:https://www.cnblogs.com/dingblog/p/4460328.html