HDOJ 1019 Least Common Multiple ―― N个数的最小公倍数求法【题解经验】

HDOJ 1019 Least Common Multiple —— N个数的最小公倍数求法【题解经验】
 
题目:
Least Common Multiple
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4624    Accepted Submission(s): 1665
Problem Description
The least common multiple (LCM) of a set of positive integers is the smallest positive integer which is divisible by all the numbers in the set. For example, the LCM of 5, 7 and 15 is 105.
 
Input
Input will consist of multiple problem instances. The first line of the input will contain a single integer indicating the number of problem instances. Each instance will consist of a single line of the form m n1 n2 n3 ... nm where m is the number of integers in the set and n1 ... nm are the integers. All integers will be positive and lie within the range of a 32-bit integer.
 
Output
For each problem instance, output a single line containing the corresponding LCM. All results will lie in the range of a 32-bit integer.
 
Sample Input
2
3 5 7 15
6 4 10296 936 1287 792 1
 
Sample Output
105
10296
 
Source
East Central North America 2003, Practice
 
Recommend
JGShining
题意:
求N个数的最小公倍数
思路:
手写代码,可以用辗转相乘法求两个数的最大公约数,然后用两数乘积除以最大公约数,所得结果即是两个数的最小公倍数。
求N个数的最小公倍数的方法具体为,先求出两个数的最小公倍数,然后再用这个最小公倍数与下一个数求最小公倍数,则得三个数的最小公倍数,然后再用这三个数的最小公倍数与第四个数求最小公倍数,得这四个数的最小公倍数……如此递推,就OK了。
代码:


#include <iostream>

#define N 10000

long
getgcd(__int64 a,__int64 b)//传说中的辗转相除法
{
    __int64
gcd,num1,num2;
    num1=(a>b)?a:b;
    num2=(a<b)?a:b;
    gcd=num2;
    num1=num1%num2;
    while
(1)
    {

        num1=num1%num2;
        if
(num1==0)
        {

            gcd=num2;
            break
;
        }

        num2=num2%num1;
        if
(num2==0)
        {

            gcd=num1;
            break
;
        }
    }

    return
gcd;
}

int main()
{

    __int64
thenum,lcm;
    int
n,num;
    int
i,j,k;
   
    scanf("%d",&n);
    for
(i=1;i<=n;i++)
    {

        scanf("%d",&num);
       
        lcm=1;
        for
(j=1;j<=num;j++)
        {

            scanf("%I64ld",&thenum);
            lcm=lcm*thenum/getgcd(lcm,thenum);
        }

       
        printf< font color="#ff00ff">(
"%I64ld\n",lcm);
    }

   
    return
0;
}

心得:

本来今晚挑了一道水题来玩的,搞定后,不小心看到这题,发现自己还没懂最小公倍数和最大公约数的求法,所以做一做。不过没想到第一次用枚举法也可以AC,584ms,�。上面代码是0ms的。

2 comments

  1. Welkin says:

    用辗转相除法求两个数的最大公约数的步骤如下:
    先用小的一个数除大的一个数,得第一个余数;
    再用第一个余数除小的一个数,得第二个余数;
    又用第二个余数除第一个余数,得第三个余数;

    这样逐次用后一个数去除前一个余数,直到余数是0为止。那么,最后一个除数就是所求的最大公约数(如果最后的除数是1,那么原来的两个数是互质数)。

    例如求1515和600的最大公约数,
    第一次:用600除1515,商2余315;
    第二次:用315除600,商1余285;
    第三次:用285除315,商1余30;
    第四次:用30除285,商9余15;
    第五次:用15除30,商2余0。

    1515和600的最大公约数是15。

    辗转相除法是求两个数的最大公约数的方法。如果求几个数的最大公约数,可以先求两个数的最大公约数,再求这个最大公约数与第三个数的最大公约数。这样依次下去,直到最后一个数为止。最后所得的一个最大公约数,就是所求的几个数的最大公约数。

  2. peter_cn says:

    这种方法效率很低。。一旦数据量非常大时就不行了。我只想到另一种稍微快点的方法,就是先求出N个数最大的那个范围之内的所有素数,复杂度nlogn,然后求出这些数中素数的最大因子数,也就是对于prim[i],最多出现int(log(max)/log(prim[i]))个,把这些素数乘起来就是结果。。求更好的算法。。

Leave a comment