【wikioi】1012 最大公约数和最小公倍数问题

题目链接

算法:辗转相除(欧几里得)

gcd(a, b)是a和b最小公倍数, lcm(a, b)是a和b的最大公倍数

gcd(a, b) == gcd(b, a%b)

时间复杂度: O(lgb)

具体证明很多的,百度即可。

代码:

int gcd(int a, int b){return (b?gcd(b, a%b):a);}

(非递归版自己推)

lcm(a, b) = a*b/gcd(a, b)

这里要注意个细节优化,在程序中应该防止溢出,即要写成

lcm(a, b) = a/gcd(a, b)*b

时间复杂度:O(lgb)

代码:

inline int lcm(int a, int b){return a / gcd(a, b) * b;}

好了到此题:【wikioi】1012

14.01.02 PS: 这是之前的代码,有点不简洁。

一般枚举算法

//暴力枚举即可
//只不过gcd(a, b) == gcd(b, a%b); lcm(a, b) == a/gcd(a, b)*b;
#include <iostream>
using namespace std;

int mymin, mymax;
void gcd(const int &a, const int &b){if(a%b==0) mymin=b; else gcd(b, a%b);}
inline int lcm(const int &a, const int &b){return (a/mymin)*b;}

int main()
{
    int tmin, tmax;
    cin >> tmin >> tmax;
    int ans = 0;
    for(int i = tmin; i <= tmax; i++)
    {
        if(i % tmin != 0 || tmax % i != 0) continue;
        for(int j = tmin; j <= tmax; j++)
        {
            if(j % tmin != 0 || i * j < tmax || tmax % j != 0) continue;
            gcd(i,j);
            if(mymin != tmin) continue;
            mymax = lcm(i, j);
            if(mymax != tmax) continue;
        	ans++;
        }
    }
    cout << ans << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/iwtwiioi/p/3521816.html